Reputation: 2747
How would one define the return type of the fn
function below?
const fn = (propName1: string, propName2: string) => {
return {
[propName1]: () => true
[propName2]: () => 'abc'
}
}
const x = fn('customProp1', 'customProp2')
console.log(x.customProp1)
console.log(x.customProp2)
e.g.
type FN = (propName: string)=> {
[propName1]: ()=>true
[propName2]: ()=>string
}
This is for two custom methods, but ideally the solution should allow for any number of custom methods and properties.
Upvotes: 4
Views: 6356
Reputation: 2747
The best solution I've found so far is as follows:
type Fn<P1 extends string, P2 extends string>={ [K in P1]: 'whatever1' } & { [K in P2]: 'whatever2' }
type Solution1 = Fn<'customProp1','customProp2'>
// { customProp1: "whatever1"; } & { customProp2: "whatever2"; }
type Identity<T> = T extends object ? {} & { [P in keyof T]: T[P] } : T
type Solution2 = Identity<Fn<'customProp1','customProp2'>>
// { customProp1: "whatever1"; customProp2: "whatever2";}
Upvotes: 0
Reputation: 4213
If you want to be safe and are ok with being a little verbose, then use TypeScript Generics:
const fn = <T extends string>(propName: T): { [_ in T]: () => true } => {
return { [propName]: () => true } as any; // a cast is sadly required for generic return types
}
const x = fn('customProp')
console.log(x.customProp) // ✅ works fine
x.notHere // ❌ compile error
Also, this will automatically support if you are passing in a generic string
type with the unsafe counterpart that the other answer used.
const y = fn("foo" as string); // same as Record<string, () => true>
y.foo; // compiles but is valid
y.asdf; // compiles but is undefined
If you wanted to be extremely safe, then you could actually change your return type when someone passes in a string
(not exact string type) using conditional types to show it could be undefined
:
const fn = <T extends string>(propName: T): { [_ in T]: Exclude<undefined | (() => true), string extends T ? never : undefined> } => {
return { [propName]: () => true } as any;
}
const x = fn("hello"); // { hello: () => true; }
x.asdf // ❌ compile error
const y = fn("hello" as string); // { [x: string]: (() => true) | undefined; }
y.foo // (() => true) | undefined
y.hello // (() => true) | undefined
Upvotes: 1
Reputation: 1378
As long as propName
is a string
, you can do:
type FN_return = {[propName: string]: ()=>true};
Upvotes: 1