microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
99.37k stars 12.31k forks source link

Type safety for enum property names #31112

Open schoel-bis opened 5 years ago

schoel-bis commented 5 years ago

Suggestion

Enums work in two directions, where an enum property value can be retrieved via AnEnum.aProperty and a property name can be retrieved via AnEnum[aValue]. In TypeScript 3.4.3, the type of the second expression is string. Instead, it should be equivalent to keyof typeof AnEnum | undefined.

Use Cases

While the nameof operator (suggested in #1579) does not exist yet, a construct such as AnEnum[AnEnum.aProperty] can currently be used to safely refer to an enum property name. Unfortunately, since the type of that expression is string it requires a cast when assigning it to a type safe target.

Examples

enum AnEnum { aProperty = 1, anotherProperty = 23, yetAnotherOne = 42 };
let target: keyof typeof AnEnum;

…

// Compilation error here: Type 'string' is not assignable to type '"aProperty" | "anotherProperty" | "yetAnotherOne"'.
target = AnEnum[AnEnum.aProperty];

Checklist

My suggestion meets these guidelines:

Howard-Lam-UnitedVanning commented 1 month ago

Would like this because for string enum, you can't really do the reverse keying like so Enum[Enum.key]. It needs to be nameof(Enum.key) / nameof Enum.key. Then, when there is refactoring, renaming will rename also the enum itself rather than just changing 1 string at a time.

Right now, my use case can be

export type RouteRecordCustom = RouteRecordRaw & {
    path: RoutePaths,
    name?: (keyof typeof RoutePaths)
};
routes: Array<RouteRecordCustom> =  = [
    {
        path: RoutePaths.Root,
        name: 'Root', //nameof RoutePaths.Root
        component: HomeView,
    },    {
        path: RoutePaths.HelloWorld,
        name: 'HelloWorld', //nameof RoutePaths.HelloWorld
        component: HelloWorld,
    },
]