我想创建一个 Discriminated Union Type,它不需要传递鉴别器值。
这是我当前的代码:
interface Single<T> {
multiple?: false // this is optional, because it should be the default
value: T
onValueChange: (value: T) => void
}
interface Multi<T> {
multiple: true
value: T[]
onValueChange: (value: T[]) => void
}
type Union<T> = Single<T> | Multi<T>
为了测试,我使用这个:
function typeIt<T>(data: Union<T>): Union<T> {
return data;
}
const a = typeIt({ // should be Single<string>
value: "foo",
onValueChange: (value) => undefined // why value is of type any?
})
const b = typeIt({ // should be Single<string>
multiple: false,
value: "foo",
onValueChange: (value) => undefined
})
const c = typeIt({ // should be Multi<string>
multiple: true,
value: ["foo"],
onValueChange: (value) => undefined
})
但是我收到了一堆错误和警告...:
const a
的 onValueChange
参数类型value
是 any
.设置时multiple: false
明确地(如在 const b
中)它被正确推断为 string
. const c
根本不起作用。我收到此错误:“类型 'string' 不可分配给类型 'string[]'”。 你知道如何解决这个问题吗?
我创建了一个 TypeScript Playground用这个代码
最佳答案
我认为编译器不能轻易推断 value
的类型回调中的参数,因为在检查回调时仍未确定对象文字的类型。
如果您没有很多联合成员,那么按预期工作的解决方案是使用多个重载:
export interface Single<T> {
multiple?: false // this is optional, because it should be the default
value: T
onValueChange: (value: T) => void
}
interface Multi<T> {
multiple: true
value: T[]
onValueChange: (value: T[]) => void
}
type Union<T> = Single<T> | Multi<T>
function typeIt<T>(data: Single<T>): Single<T>
function typeIt<T>(data: Multi<T>): Multi<T>
function typeIt<T>(data: Union<T>): Union<T> {
return data;
}
const a = typeIt({ // is Single<string>
value: "foo",
onValueChange: (value) => undefined // value is typed as expected
})
const b = typeIt({ // is Single<string>
multiple: false,
value: "foo",
onValueChange: (value) => undefined
})
const c = typeIt({ // is be Multi<string>
multiple: true,
value: ["foo"],
onValueChange: (value) => undefined
})
关于带有默认值和类型推断的 TypeScript 判别联合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54030827/