Kan jag definiera en returtyp i TypeScript baserat på värdena i en array-egenskap?


Jag försöker definiera en funktions returtyp baserat på värdena i en array-egenskap hos ett objekt.

Här är ett exempel på vad jag försöker åstadkomma:

type Table = { columns: { name: string }[] };
const table = { columns: [{ name: 'col1' }, { name: 'col2' }] };

const fn = (table: Table): Record<????, any> => {
    // some logic
};

const result = fn(table);
// Expected behavior:
result.col1; // should be accessible
result.col2; // should be accessible

Finns det ett sätt att uppnå detta i TypeScript?

Det liknar det tillvägagångssätt som föreslås i detta svar, men den lösningen verkar bara fungera om jag skickar arrayen direkt som en parameter till funktionen. I mitt fall är arrayen nästlad inom ett objekt (table.columns),

Tack i förväg.

Svar #1

För att få detta att fungera bör du använda as const för exakt typning och använda egenskapsåtkomstsyntax:

Lekplats

type Table = { columns: { name: string }[] };
const table = { columns: [{ name: 'col1' }, { name: 'col2' }] } as const satisfies Table;

const fn = <T extends Table>(table: T): {[K in T['columns'][number]['name']]: any} => {
    return 1 as any;
}

const result = fn(table);
// Expected behavior:
result.col1; // should be accessible
result.col2; // should be accessible

Svar #2

Följande verkar rätt:

type Table = { columns: { name: string }[] };
const table = { columns: [{ name: 'col1' }, { name: 'col2' }] } as const satisfies Table;

type Subkey<X> = X extends { columns: Array<{ name: infer Y }> } ? Y : never;

type R = Subkey<typeof table>
declare const fn: <T extends Table>(table: T) => Record<Subkey< T>, number>;

const result = fn(table);
result.col1; // is accessible
result.col2; // is accessible
result.whoopsieDoodle; // <-- not accessible