New to Typescript... is it possible to write a generic function in typescript which will print the keys of a given type? Something like:
const getKeys = <T>(): string[] => { ??? }
interface A {
a: string,
b: number
}
getKeys<A>(); // returns ["a", "b"]
Rationale: I want to write a function which will get a raw object and a type and will check if it contains all the keys from that type. I don't want to pass the keys for every type!
const checkKeys = <T>(rawData: any): boolean => { ??? }
interface A {
a: string,
b: number
}
const wrong = {
x: "aaa",
y: "bbb",
};
checkKeys<A>(wrong); // return false
I can write something like this:
const checkKeys = <T, K = keyof T>(data: any, ...keys: K[]) => {
for (const key of keys) {
if (!data[key]) {
return false;
}
}
return true;
}
interface A {
a: string,
b: number,
}
const right = { a: "a", b: "b" };
const wrong = { c: "a", b: "b" };
checkKeys<A>(right, "a", "b")); // returns true
checkKeys<A>(wrong, "a", "b")); // returns false
But I always have to pass the keys for every type I want to call it on, really annoying!
I know that Typescript is just the type system and we need something at runtime, but is there a way that Typescript can generate the values for keys
at compile time since it knows them in my case and even can check that I am passing only the acceptable values for keys
parameter? If it is that smart during compile time, it could generate an array for me when compiling to Javascript. Is there a way that I'm not aware of?
CodePudding user response:
Typescript won't generate code for you.
The closest thing you could have is creating the possible keys in advance :
const keys = ['a', 'b', 'c'] as const;
type Keys = typeof keys[number] // 'a' | 'b' | 'c'
type Foo = Record<Keys, string>;
const foo: Foo = {
a: 'foo',
b: 'bar',
c: 'baz',
}
Here keys
is a array you can iterate over.
CodePudding user response:
const sample = {
a: '123',
b: 123
}
type Dict = { [key: string | number]: any}
type CheckKeys<T extends Dict, S extends Dict> = keyof T extends never ? false : (keyof S extends keyof T ? true : false)
function checkKeys<
T extends Dict,
S extends Dict,
>(data: T, smp: S): CheckKeys<T, S> {
const smpKeys = Object.keys(smp)
for (const key in data) {
if (!(key in smpKeys)) return false as CheckKeys<T, S>
}
return true as CheckKeys<T, S>
}
const right = { a: "a", b: "b" };
const wrong = { c: "a", b: "b" };
// const checkRight: true
const checkRight = checkKeys(right, sample);
// const checkWrong: false
const checkWrong = checkKeys(wrong, sample);