Reputation: 113
I am unable to get the following code to work.
I am trying to fetch some data and handling all the falsy/error cases and then passing on the cleaned data to another function. But the typings don't seem to match when I call the second function.
Type 'Error | number[]' is not assignable to type '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)
}
Upvotes: 2
Views: 131
Reputation: 9484
You can work around the issue by moving your type checking logic into a type predicate. Here is your example, modified with 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)
}
Upvotes: 1
Reputation: 2508
Short Answer: Remove type Error from SomeType.a.
Long Answer:
a: number[] | null;
a can be either array of number or null. It is perfectly fine because either a exits or it doesn't.
a: number[] | null | Error;
Here, type Error is causing problem because Error does not have same property/functions that array of number has. For this to work, all the types must have some similar properties.
Another solution: Typecast the obj to appropiate type:
useData(<{a: number[], b: number[]}>obj)
Upvotes: 0