javascript - TypeScript: Kan du definere en returtype-struktur basert på et argument til funksjonen?


Jeg prøver å lage en funksjon som tar et strengargument og returnerer et objekt som har denne strengen som en nøkkel.

for eksempel (pseudokode): test('bar') => {bar: ...}

Jeg er ikke sikker på hvordan jeg skal få returtypen riktig for denne funksjonen.

Denne koden gir meg riktig returtype, men TS-kompilatoren synes ikke at objektet jeg returnerer samsvarer med returtypen?

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

Noe slik vil fungere bra. Men det gir meg ikke den sterkt typede returtypen jeg ser etter:

function test2<K extends string>(key: K){
  return { [key]: 6 }
}
const foo2 = test2<'bar'>('bar')
// foo2 type: {[x: string]: number}  // no good

All hjelp med dette ville bli svært satt pris på!

Svar #1

Finjusterer første forsøk litt, og dette ser ut til å fungere:

function test<K extends string>(key: K) {
  return { [key]: 6 } as {[prop in K]: number}
}

const foo = test('bar') // { bar: number }

Å måtte kaste det virker litt merkelig for meg, though.

Svar #2

du kan gjøre masse ting med utvidede typinger.

Som @SnailCrusher viste, kan du definere returtypen statisk. Det finnes også en måte å dynamisk tilordne typer til de returnerte egenskapene på:

// 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; }

Dette vil også legge til rik kontekst i IDE-en din om gyldige parametere.

Du kan lese mer om dette i Typescript-dokumentasjonen: https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types-and-index-signatures

Relaterte artikler