带有默认和类型推断的 TypeScript 区分联合类型
TypeScript Discriminated Union Type with default and type inference
我想创建一个可区分的联合类型,它不需要传递鉴别器值。
这是我当前的代码:
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
})
但是我收到一堆错误和警告...:[=21=]
在const a
的onValueChange
中,参数value
的类型是any
。当显式设置 multiple: false
时(如 const b
),它会被正确推断为 string
.
const c
根本不起作用。我收到此错误:"Type 'string' is not assignable to type '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
})
我想创建一个可区分的联合类型,它不需要传递鉴别器值。
这是我当前的代码:
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
})
但是我收到一堆错误和警告...:[=21=]
在
const a
的onValueChange
中,参数value
的类型是any
。当显式设置multiple: false
时(如const b
),它会被正确推断为string
.const c
根本不起作用。我收到此错误:"Type 'string' is not assignable to type '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
})