当使用引用时,Typescript 的 Omit 不会显示错误
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
interface objInterface {
first: string;
second: string;
}
const obj = {
first: "first",
second: "second"
};
const out: Omit<objInterface, "first"> = obj;
我本以为这会有一些智能感知错误,但实际上没有。然而,这个确实显示了一些错误,有人知道为什么吗?
const out: Omit<objInterface, "first"> = {
first: 'first',
second: 'second'
};
答案#1
除了@kingdaro关于对象字面量的多余属性检查的正确观点之外,
Omit<T,K> 的定义只是扩展了 T 的类型,使其不包含在 K 处的已知属性(“我不知道或者不关心 K 是否是一个属性;我会忽略它。”),这并不等同于在 K 处禁止一个属性。也就是说,T 是 Omit<T, K> 的子类型,任何 T 类型的值也可以赋值给 Omit<T, K> 类型。如果你的意图是实际上在 K 处禁止一个属性,你可以(某种程度上)通过指定 K 属性为可选且其值类型为 never(或 undefined,见下文)来实现。我们称之为 ForcefullyOmit<T, K>:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type ForcefullyOmit<T, K extends keyof T> = Omit<T, K> & Partial<Record<K, never>>;
让我们看看它是否有效:
interface ObjInterface {
first: string;
second: string;
}
const obj = {
first: "first",
second: "second"
};
const out: ForcefullyOmit<ObjInterface, "first"> = obj; // error
// types of property "first" are incompatible
// string is not assignable to undefined
看起来不错。
这只是“某种程度上”禁止该键,因为它仍然允许该键的属性类型为 undefined(或 never),但这是 TypeScript 中的一种未解决的问题……语言并不总是区分缺失的属性和 undefined 的属性。
如果你的用例确实需要 ForcefullyOmit 的更严格行为,那就由你决定了。无论如何,希望这能帮到你;祝你好运!
答案#2
TypeScript 只有在将对象定义为字面量时才会对多余属性报错,这是设计使然。https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks
