TypeScript-type med egenskaper på et objekt som inneholder en spesifikk type


Jeg vil lage en generisk type CompatibleProp<T, U> som vil løse seg til en strengtype som inneholder alle egenskapene til T som har verdier av typen U.

Eksempel på hva jeg ønsker å oppnå:

class C {
    a: number;
    b: string;
    c: Date;
}

type DatePropOfC = PropCompatible<C, Date>;  // "c"
type NumberOrStringPropOfC = PropCompatible<C, number | string>;  // "a" | "b"
type AnyPropOfC = PropCompatible<C, any>;  // same as keyof C

Er dette mulig å oppnå med TypeScript 2.8 betingede typer? Jeg har prøvd noen kombinasjoner, men finner ikke den rette.

Svar #1

Selvfølgelig kan du gjøre dette med betingede typer og en ekstra typeforespørsel

type PropCompatible<T, TProp> = { [P in keyof T] : T[P] extends TProp ? P : never}[keyof T]

Rediger

Mens typen ovenfor fungerer godt for å få en union av nøkler av en bestemt type, har den i konteksten av en generisk funksjon ulempen at kompilatoren ikke kan følge med på at egenskaps-tilgangen vil være av den gitte egenskapstypen. For å oppnå dette må vi uttrykke begrensningen om at vi kun tar nøkler av en bestemt feltstype på en annen måte. Vi kan gjøre dette ved å bruke en ekstra typeparameter K for nøkkelen og kreve at for K er typen til feltet i T av den gitte typen (Date for eksempel)

function getDate<T extends Record<K, Date>, K extends string>(t: T, k: K): Date {
    return t[k];
}

Relaterte artikler