Open VagabondOfHell opened 3 years ago
I don't think it would be appropriate for nameof<T>()
to return keyof T
since nameof<T>(a => a.x.y)
returns "y", which is probably not a key of T. However, a variant which does return keyof would be very helpful.
Perhaps we could have a new function, such as:
declare namespace nameof {
function key<T>(func: (obj: T) => any): keyof T;
}
Usage:
interface A {
x: string;
y: { z: number };
}
const name: keyof A = nameof.key<A>(a. => a.x);
The library could trigger an error if you attempt to use a nested property:
nameof.key<A>(a => a.y.z); // ERROR: 'z' is not a key of A
Would this be a desirable addition to the library?
That reasoning makes perfect sense.
I think adding it as a separate function is a great idea, so yes, your proposal would be a desirable addition in my eyes
@bretcope is correct that it can't be typed that way. There's not a way to inject functionality into type checking since transformations happen afterwards.
For this you might just want to just do the following or something along these lines:
function nameof<TObj>(key: keyof TObj) {
return key;
}
const result = nameof<A>("x");
@dsherret that's a good idea. I thought that might not work with the refactoring tools I use, but it does. I should have checked first!
@dsherret Just to confirm, what you're saying is it can't happen at compile time, only runtime?
When using a function such as
doSomethingByName ( name: keyof(State), value: string ): void { this.state[name] = value }
With nameof you get a compile time error indicating that the type doesn't match. While we could add a cast to the call like
nameof<State>(o => o.type) as keyof(State)
I was wondering if we could have the return type of nameof be keyof(T) instead for all of the nameof operations that use the generic form.
This would allow us to remove the cast and just call
doSomethingByName(nameof<State>(o => o.type), 'myNewValue')