'Enforce generic type parameter to be enum
This is what I want to achieve:
// first.ts
export enum First {
One,
Two,
Three
}
// second.ts
export enum Second {
One,
Two,
Three
}
// factory.ts
// for those who don't know, Record is just an object. key value pairs
type NotWorkingType<T> = Record<T , string>;
// I can't get either of these objects working.
// What's an important detail here is that First and Second enums are external, and at any time a "Third" can be created and should just work.
const testObject: NotWorkingType<First> = {
[First.One]: 'first',
[First.Two]: 'second',
[First.Three]: 'third',
}
const testObject: NotWorkingType<Second> = {
[First.One]: 'first',
[First.Two]: 'second',
[First.Three]: 'third',
}
Currently, the problem occurs here:
// Type 'T' does not satisfy the constraint 'string | number | symbol'.
// Type 'T' is not assignable to type 'symbol'.(2344)
// |
// v
type NotWorkingType<T> = Record<T , string>;
I've tried to use k in keyof typeof T like this as well:
type NotWorkingOtherType<T> = {
// 'T' only refers to a type, but is being used as a value here.(2693)
// |
// v
[k in keyof typeof T]: string;
}
It seems like no matter which combination I use with generic parameters, it won't work with enums.
Am I missing something here?
Solution 1:[1]
TS is trying to tell you that the Key in Record<Key, Value> has to be either string, number, or symbol. That's because JS object property names can only be one of those types (and under the hood numbers are turned to strings). Thus you'll need to promise (using the extends keyword) that the T in type NotWorkingType<T> = Record<T, string> can be assigned to the union string | number | symbol. You're using plain enums, and their member values are assignable to number:
export enum First {
One, // First.One === 0
Two, // First.Two === 1
Three // First.Three === 2
};
type WorkingType<T extends number> = Record<T, string>;
const testObject: WorkingType<First> = {
[First.One /* === 0 */]: "first",
[First.Two /* === 1 */]: "second",
[First.Three /* === 2 */]: "third",
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Emma Koskinen |
