Typescript Har typen til egenskapen fra et objekt


Jeg prøver å lage en generell react-skjema-reducer. For det må "Value" ha typen T etter "name". Jeg er ikke sikker på at jeg er omfattende, så her er et eksempel som vil være tydeligere:

Eksempel :

type RandomObject = { test1: number, test2: string, test3: string[] }

type ActionChangeInput<T> = {
  name: keyof T
  value: typeof T["name"] // Get type of name
}

Jeg vil at verdi skal være et tall fordi verdien av navn er "test1" og typen til "test1" er tall.

const a: ActionChangeInput<RandomObject> = {
  name: "test1", // type is "test1" | "test2" | "test3"
  value: 12931 // Expect number here
}

Beklager hvis det ikke er klart, men det er vanskelig å forklare noe jeg ikke forstår (det er derfor jeg er her).

Svar #1

Det du ønsker er at ActionChangeInput<T> skal løse seg til en union av alle muligheter. Du kan gjøre det med en avbildet type som mapper over hver egenskap av T og lager en type som parer navn- og verdityper kun for den egenskapen.

Noe som:

type ActionChangeInput<T> = {
  [K in keyof T]: {
    name: K
    value: T[K]
  }
}[keyof T]

Dette kartlegger over hver egenskap i T med [K in keyof T], og oppretter en objekttype for hver kombinasjon av name som K og verdi som T[K].

Du indekserer deretter det resulterende objektet med dets egne nøkler for å få en union av dets verdier.

Med RandomObject-typen, bør det løse seg til:

type RandomObject = { test1: number, test2: string, test3: string[] }

type Test = ActionChangeInput<RandomObject>
/*
| { name: 'test1', value: number }
| { name: 'test2', value: string }
| { name: 'test3', value: string[] }
*/

Så enhver gyldig verdi av den typen må ha en name og verditype som samsvarer i den listen over unioner.

Resten oppfører seg nå som du ville forventet:

type RandomObject = { test1: number, test2: string, test3: string[] }

// fine
const a: ActionChangeInput<RandomObject> = {
  name: "test1",
  value: 12931,
}

// error
const b: ActionChangeInput<RandomObject> = {
  name: "test2",
  value: 12931, // Type 'number' is not assignable to type 'string'.(2322)
}

Se lekeplass

Relaterte artikler