dsherret / ts-nameof

nameof in TypeScript
MIT License
492 stars 23 forks source link

Return Type of KeyOf #112

Open VagabondOfHell opened 3 years ago

VagabondOfHell commented 3 years ago

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')

bretcope commented 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?

VagabondOfHell commented 3 years ago

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

dsherret commented 3 years ago

@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");
bretcope commented 3 years ago

@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!

VagabondOfHell commented 3 years ago

@dsherret Just to confirm, what you're saying is it can't happen at compile time, only runtime?