是否可以修改 TypeScript 中文字的推断类型?
Is it possible to modify the inferred type of a literal in TypeScript?
考虑以下尝试有条件地将 属性 添加到具有推断类型的对象的代码:
const foo = {
a: 1,
b: 2,
};
if (bar) {
foo.c = 3; // Error: Property 'c' does not exist on type '{ a: number; b: number; }'.(2339)
}
可以通过将 foo
的类型显式声明为 { a: number; b: number; c?: number; }
或使用 spread 有条件地添加 c
:
来消除错误
const foo = {
a: 1,
b: 2,
...(bar ? { c: 3 } : {}),
};
但是,假设我们想保留原始代码结构,但我们也想避免必须显式声明可以推断的属性。是否有任何解决方案可以同时满足这两个要求?例如,是否可以以某种方式调整推断类型,例如:
const foo = {
a: 1,
b: 2,
} as { ...; c?: number; }; // Example, does not work
这不是很漂亮,但它有效:a
和 b
的 属性 类型是推断的,不必冗余声明。
function withMissingProps<T>() {
return function<S>(obj: S): S & Partial<T> {
return obj;
}
}
const foo = withMissingProps<{ c: number }>()({
a: 1,
b: 2
});
if(Math.random() > 0.5) {
foo.c = 1;
}
有两个类型参数,T
和 S
,分别用于声明的属性和推断的属性。不幸的是,如果一个函数有两个类型参数,那么您必须同时提供或推断两者;解决方案是柯里化函数,尽管这意味着要多一对括号。
我还发现了这个 hack,不幸的是编译为 Object.assign
,因此运行时成本非零:
const foo = {
a: 1,
b: 2,
...{} as {
c?: number,
},
};
考虑以下尝试有条件地将 属性 添加到具有推断类型的对象的代码:
const foo = {
a: 1,
b: 2,
};
if (bar) {
foo.c = 3; // Error: Property 'c' does not exist on type '{ a: number; b: number; }'.(2339)
}
可以通过将 foo
的类型显式声明为 { a: number; b: number; c?: number; }
或使用 spread 有条件地添加 c
:
const foo = {
a: 1,
b: 2,
...(bar ? { c: 3 } : {}),
};
但是,假设我们想保留原始代码结构,但我们也想避免必须显式声明可以推断的属性。是否有任何解决方案可以同时满足这两个要求?例如,是否可以以某种方式调整推断类型,例如:
const foo = {
a: 1,
b: 2,
} as { ...; c?: number; }; // Example, does not work
这不是很漂亮,但它有效:a
和 b
的 属性 类型是推断的,不必冗余声明。
function withMissingProps<T>() {
return function<S>(obj: S): S & Partial<T> {
return obj;
}
}
const foo = withMissingProps<{ c: number }>()({
a: 1,
b: 2
});
if(Math.random() > 0.5) {
foo.c = 1;
}
有两个类型参数,T
和 S
,分别用于声明的属性和推断的属性。不幸的是,如果一个函数有两个类型参数,那么您必须同时提供或推断两者;解决方案是柯里化函数,尽管这意味着要多一对括号。
我还发现了这个 hack,不幸的是编译为 Object.assign
,因此运行时成本非零:
const foo = {
a: 1,
b: 2,
...{} as {
c?: number,
},
};