javascript - Kan inte få TypeScript-typningarna att matcha
Jag kan inte få följande kod att fungera.
Jag försöker hämta lite data och hantera alla falska/felaktiga fall och sedan skicka vidare den rensade datan till en annan funktion. Men typningen verkar inte stämma när jag kallar den andra funktionen.
Typen 'Error | number[]' kan inte tilldelas typen 'number[]'
interface SomeType {
a: number[] | null | Error
b: number[] | null
}
type Omit <T, K> = Pick<T, Exclude<keyof T, K>>
type ExcludeUnusableValues<T,K extends keyof T,C = Error | null>
= Omit<T, K> & {
[a in K]-? : Exclude<T[a], C>
}
function fetchData() {
const obj: SomeType = {
a: [1, 2, 3],
b: null
}
if (obj.a === null || obj.a instanceof Error) {
return null
}
// Type 'Error | number[]' is not assignable to type 'number[]'
useData(obj)
}
function useData(param1: ExcludeUnusableValues < SomeType, 'a' > ) {
console.log(param1)
}TypeScript-lekplatslänk
Svar #1
Du kan kringgå problemet genom att flytta din typkontrollslogik till en typ-predikat. Här är ditt exempel, modifierat med isUsableType:
interface SomeType {
a: number[] | null | Error
b: number[] | null
}
function isUsableType(obj: SomeType): obj is ExcludeUnusableValues < SomeType, 'a' > {
return obj.a!==null && !(obj.a instanceof Error)
}
type Omit <T, K> = Pick<T, Exclude<keyof T, K>>
type ExcludeUnusableValues<T,K extends keyof T,C = Error | null>
= Omit<T, K> & {
[a in K]-? : Exclude<T[a], C>
}
function fetchData() {
const obj: SomeType = {
a: [1, 2, 3],
b: null
}
if (isUsableType(obj)) {
useData(obj)
} else return null;
}
function useData(param1: ExcludeUnusableValues < SomeType, 'a' > ) {
console.log(param1)
}
Svar #2
Kort svar: Ta bort typen Error från SomeType.a.
Utförligt svar:
a: number[] | null;
a kan vara antingen en array av nummer eller null. Det är helt okej eftersom antingen finns a eller så finns den inte.
a: number[] | null | Error;
Här orsakar typen Error problem eftersom Error inte har samma egenskaper/funktioner som en array av nummer har. För att detta ska fungera måste alla typer ha vissa liknande egenskaper.
En annan lösning: Typkasta obj till lämplig typ:
useData(<{a: number[], b: number[]}>obj)
