I want to write a TypeScript function that accepts only certain strings, which are the property names of a specified type, but these properties must have a type of string, number or Date. This function returns another function that accepts the original object (of which the property names were selected) and returns the specified property (actually it does something else, but this is the simplest case that produces the same problem)
I tried it like this
"use strict";
type InstancePropertyNames<T, I> = {
[K in keyof T]: T[K] extends I ? K : never;
}[keyof T];
type StringPropertyNames<T> = InstancePropertyNames<T, string>;
type NumberPropertyNames<T> = InstancePropertyNames<T, number>;
function doSomething<T extends object>(
key:
| StringPropertyNames<T>
| NumberPropertyNames<T>
| InstancePropertyNames<T, Date>
) {
return function(obj: T) {
const res = obj[key];
return res;
}
}
function doSomethingEasy<T extends object>(
obj: T,
key:
| StringPropertyNames<T>
| NumberPropertyNames<T>
| InstancePropertyNames<T, Date>
) {
const res = obj[key];
return res;
}
type Test = {
asdf: string;
foo: number;
bar: boolean;
qux: Date;
};
const test: Test = {
asdf: "asdf",
foo: 42,
bar: true,
qux: new Date()
}
const res = doSomething<Test>("asdf")(test);
console.log(res);
const resEasy = doSomethingEasy(test, "asdf");
console.log(resEasy);
The problem is now that the type of res inside the nested function is something complex (instead of simply number | string | Date), also in doSomethingEasy. Is there any way to simplify the type of the property in the nested function to the primitive types?