带有映射类型的 Typescript 类型推断无法正常工作
Typescript type inference with mapped types does not work correctly
我正在尝试使用 TypeScript 在我的应用程序中提供类型安全。
我有一些带有必填“值”字段的类型。他们还有一个“类型”属性,我用它来缩小类型。
然后我创建了这种类型的联合类型。我可以通过检查类型字段来检查其中的内容。
然后我想创建另一种类型,它将具有第一个联合类型的所有字段,但值字段是可选的(可以未定义)。不幸的是,这种类型的行为不符合我的要求。
这是我的代码的简化版本,用于演示问题:
type First = {
type: 'FIRST';
value: number;
uniqueFieldInFirst: string;
};
type Second = {
type: 'SECOND';
value: string;
uniqueFieldInSecond: string;
};
type FirstOrSecond = First | Second;
type Opt<T extends FirstOrSecond>
= Omit<T, 'value'> // This way we add all fields from FirstOrSecond type expect the 'value'
& Partial<T>; // And now we all remaining fields (only value, but with "?")
const example: Opt<First> = {
type: 'FIRST',
value: 1234,
uniqueFieldInFirst: 'abc'
}; // works
const another: Opt<Second> = {
type: 'SECOND',
value: '1234',
uniqueFieldInSecond: 'abc'
}; // works
const oneMore: Opt<Second> = {
type: 'SECOND',
value: undefined,
uniqueFieldInSecond: 'abc'
}; // works
const secondTest = (optional: Opt<FirstOrSecond>) => {
if (optional.value !== undefined) {
const firstOrSecond: FirstOrSecond = optional;
// here comes the error:
// TS2322: Type 'Opt<FirstOrSecond>' is not assignable to type 'FirstOrSecond'.
// Type 'Omit<FirstOrSecond, "value"> & Partial<First>' is not assignable to type 'FirstOrSecond'.
// Type 'Omit<FirstOrSecond, "value"> & Partial<First>' is not assignable to type 'First'.
// Types of property 'value' are incompatible.
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.
}
};
我的目标是创建这样的工作函数:
function mapToFirstOrSecond<T extends FirstOrSecond>(optional: Opt<T>): T | undefined {
if (optional.value !== undefined) {
return optional as T;
}
return undefined;
}
但是没有转换就不行。
您可以使用用户定义的类型保护来确保 Typescript 编译器使用正确的类型:
function isFirstOrSecond(optional: any): optional is FirstOrSecond {
return optional.value !== undefined;
}
然后:
if (isFirstOrSecond(optional)) {
// ...
}
我正在尝试使用 TypeScript 在我的应用程序中提供类型安全。
我有一些带有必填“值”字段的类型。他们还有一个“类型”属性,我用它来缩小类型。 然后我创建了这种类型的联合类型。我可以通过检查类型字段来检查其中的内容。
然后我想创建另一种类型,它将具有第一个联合类型的所有字段,但值字段是可选的(可以未定义)。不幸的是,这种类型的行为不符合我的要求。
这是我的代码的简化版本,用于演示问题:
type First = {
type: 'FIRST';
value: number;
uniqueFieldInFirst: string;
};
type Second = {
type: 'SECOND';
value: string;
uniqueFieldInSecond: string;
};
type FirstOrSecond = First | Second;
type Opt<T extends FirstOrSecond>
= Omit<T, 'value'> // This way we add all fields from FirstOrSecond type expect the 'value'
& Partial<T>; // And now we all remaining fields (only value, but with "?")
const example: Opt<First> = {
type: 'FIRST',
value: 1234,
uniqueFieldInFirst: 'abc'
}; // works
const another: Opt<Second> = {
type: 'SECOND',
value: '1234',
uniqueFieldInSecond: 'abc'
}; // works
const oneMore: Opt<Second> = {
type: 'SECOND',
value: undefined,
uniqueFieldInSecond: 'abc'
}; // works
const secondTest = (optional: Opt<FirstOrSecond>) => {
if (optional.value !== undefined) {
const firstOrSecond: FirstOrSecond = optional;
// here comes the error:
// TS2322: Type 'Opt<FirstOrSecond>' is not assignable to type 'FirstOrSecond'.
// Type 'Omit<FirstOrSecond, "value"> & Partial<First>' is not assignable to type 'FirstOrSecond'.
// Type 'Omit<FirstOrSecond, "value"> & Partial<First>' is not assignable to type 'First'.
// Types of property 'value' are incompatible.
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.
}
};
我的目标是创建这样的工作函数:
function mapToFirstOrSecond<T extends FirstOrSecond>(optional: Opt<T>): T | undefined {
if (optional.value !== undefined) {
return optional as T;
}
return undefined;
}
但是没有转换就不行。
您可以使用用户定义的类型保护来确保 Typescript 编译器使用正确的类型:
function isFirstOrSecond(optional: any): optional is FirstOrSecond {
return optional.value !== undefined;
}
然后:
if (isFirstOrSecond(optional)) {
// ...
}