Reputation: 1424
I'm trying to create a function that will take a string argument and return an object that has this string as a key.
for example (pseudo code):
test('bar') => {bar: ...}
I'm not sure how to get the return type right for this function.
This code gives me the right return type, but the TS compiler doesn't think my returned object matches the return Type?
function test<K extends string>(key: K):{[prop in K]: number} {
return { [key]: 6 } // error: not assignable
}
const foo = test<'bar'>('bar')
// foo type: {bar: number} // return type is good
Something like this will work fine. But does not give me the strongly types return type I am looking for:
function test2<K extends string>(key: K){
return { [key]: 6 }
}
const foo2 = test2<'bar'>('bar')
// foo2 type: {[x: string]: number} // no good
Any help with this would be much appreciated!
Upvotes: 3
Views: 1718
Reputation: 2150
you can do lots of stuff with extended typings.
Like @SnailCrusher showed, you can define the return type staticly. There is also a way to dynamically assign typings to the returned props:
// this interface defines potential parameters to the methods
interface Tokens {
foo: number,
bar: string,
}
// return one prop in the result object
// this methods only accept keys of the interface Tokens as valid inputs
function test<K extends keyof Tokens>(key: K) {
switch(key) {
case 'foo': return { [key]: 0 } as {[prop in K]: Tokens[K]}
case 'bar': return { [key]: '0' } as {[prop in K]: Tokens[K]};
}
return { [key]: undefined } as {[prop in K]: Tokens[K]}
}
const bar = test('bar') // { bar: string }
const foo = test('foo') // { foo: number }
// return full interface in the result object
// the given token will be set an all other props will be optional
function test2<K extends keyof Tokens>(key: K) {
return { [key]: 6 } as {[prop in K]: Tokens[K]} & {[P in keyof Tokens]?: Tokens[P];}
}
const bar2 = test2('bar') // { foo?: number; bar: string; }
const foo2 = test2('foo') // { foo: number; bar?: string; }
This will allso add rich context to your IDE on valid parameters.
You can read mor of this in the Typescript documentation: https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types-and-index-signatures
Upvotes: 2
Reputation: 9134
I don't understand why you need generics here, what speaks against simply doing
function test(key: string): { [key: string]: number } {
return { [key]: 6 };
}
Upvotes: 1
Reputation: 1424
Tweaking the first attempt a bit and this seems to work:
function test<K extends string>(key: K) {
return { [key]: 6 } as {[prop in K]: number}
}
const foo = test('bar') // { bar: number }
Having to cast it seems a bit strange to me though.
Upvotes: 2