In order to call Object.keys
you should have an object.
Hence, you have to pass this object as an argument to keysof
function, like this:
const keysof=<T,>(obj: T) => Object.keys(obj) as Array<keyof T>;
Generic type T is erased after compilation.
It means that if you want to remove obj
argument and leave only T
, like this:
const keysof = <T,>() => Object.keys() as Array<keyof T>;
you will end up with this:
const keysof = () => Object.keys();
Hence, you can get rid only explicit return type, like this:
export function keysof<T>(obj:T) {
return Object.keys(obj) as Array<keyof T>;
}
I think you should be aware of Array<keyof T>
drawback. Because it allows you to use duplicates in your array. Consider this exmaple:
const obj = { age: 42, name: 'John' }
const keys: Array<keyof typeof obj> = ['age', 'age', 'age'] // no compilation error
Is this what you want ? I don't think so. Because Object.keys
can't produce duplicates in the result array.
There is another one approach. It also has own drawbacks :)
// credits goes to https://twitter.com/WrocTypeScript/status/1306296710407352321
type TupleUnion<U extends string, R extends any[] = []> = {
[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];
const obj = { age: 42, name: 'John' }
const keys: TupleUnion<keyof typeof obj> = ['age', 'age', 'age'] // error
Above code causes a compilation error, just as you expect. But you can also boil some water on your PC/laptop since it CPU resurse consuming approach. Also it has own recursion limitations.
Here you can find step by step explanation of TupleUnion
type utility
TL;TR
TupleUnion
- produces a permutation of all possible Object.keys
results