The Omit
utility type只是从对象类型的known个键中删除一组属性.但对象通常被允许具有比其类型已知的更多的属性.对象类型不是"精确的"(如microsoft/TypeScript#12936中所要求的);如果在类型中没有提到键,则该属性是未指定/未知的,并不被禁止.
否则你永远也用不上extended interfaces:
interface Foo {
x: string;
}
function processFoo(foo: Foo) {
console.log(foo.x.toUpperCase())
};
interface Bar extends Foo {
y: number
}
const bar: Bar = { x: "abc", y: 123 };
processFoo(bar); // <-- this is allowed because every Bar is also a Foo
在上面的定义中,S省略了对y
属性的任何提及,但这并不能阻止Bar
对其进行扩展.从类型中省略属性只会使其接受more项内容,而不是更少.
这意味着IUSerModel
是类型Omit<IUserModel, 'password'>
的完全有效值.
无法编写拒绝所有可能的多余属性的类型.这将需要精确的类型,或microsoft/TypeScript#17867中所要求的某种"REST index signature",或其他相关功能.
但是您可以sort of编写一个类型来禁止specific的超额属性.你可以把它设为the impossible never
type的optional property(所以它可以存在或不存在)(所以你不容易找到让它存在的方法).这相当接近于禁止一项房产,尽管也有一些边缘情况.
无论如何,这意味着我们可以编写自己的OmitAndProhibit
实用程序类型,省略一组属性,然后将它们作为类型never
的可选属性添加回来:
type OmitAndProhibit<T, K extends string> =
Omit<T, K> & { [P in K]?: never };
让我们试一试吧:
type IUserDto = OmitAndProhibit<IUserModel, 'password'>
function createUser(user: IUserModel): IUserDto {
const newUser: IUserModel = {
fullname: user.fullname,
username: user.username,
password: user.password
}
return newUser; // error!
// Type 'IUserModel' is not assignable to type '{ password?: undefined; }'.
}
看上go 不错.编译器对newUser
不满意,因为它有一个值为string
的password
属性,而它需要类型never
的可选属性.嗯,或者undefined
(除非您启用了the --exactOptionalPropertyTypes
compiler option,否则总是允许为可选属性设置undefined
),但这仍然非常接近.
Playground link to code个