It's important to note that TypeScript types cannot be used to validate object values at runtime; for that, a regex or a validation library like zod or joi would be necessary. String literals can only be validated at compile time.
However, if TypeScript had support for recursive template literal types, creating a type as described could be straightforward:
type Param = number;
type Params = '' | `${Params}, $Paraam`
type Func = `func(${Params})`
Unfortunately, the code above results in an error due to circular reference within the Params
type.
Type alias 'Params' circularly references itself.ts(2456)
As a workaround, you have to manually list out the types with an upper limit:
type N = number;
type Params = ''
| `${N}`
| `${N}, ${N}`
| `${N}, ${N}, ${N}`
| `${N}, ${N}, ${N}, ${N}`
| `${N}, ${N}, ${N}, ${N}, ${N}`
| `${N}, ${N}, ${N}, ${N}, ${N}, ${N}`
| `${N}, ${N}, ${N}, ${N}, ${N}, ${N}, ${N}`
type Func = `func(${Params})`
const f: Func = 'func(1, 2, 3, 4, 5, 6, 7)'; // OK
const g: Func = 'func 1, 2, 3, 4, 5, 6, 7 '; // Error
A utility type could potentially eliminate the need for manual listing, but without support for recursive template literal types, there will still be an upper limit.