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
