我对createUser函数的返回类型有问题.

interface IUserModel{
    fullname: string
    username: string
    password: string
}

type IUserDto = Omit<IUserModel, 'password'>

function createUser(user: IUserModel): IUserDto {
    // actually this calls a create method from a user repository
    const newUser: IUserModel = {
        fullname: user.fullname,
        username: user.username,
        password: user.password
    }
    
    /* 
     typescript does not warn me that the password property 
     should not be there
    */
    return newUser
}

返回对象文字对我来说不是一个有效的解决方案,我想让TypeScrip警告我有问题

有没有办法让函数只返回IUserDto,而不需要额外的属性?

推荐答案

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 typeoptional 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不满意,因为它有一个值为stringpassword属性,而它需要类型never的可选属性.嗯,或者undefined(除非您启用了the --exactOptionalPropertyTypes compiler option,否则总是允许为可选属性设置undefined),但这仍然非常接近.

Playground link to code

Typescript相关问答推荐

如果我有对象的Typescript类型,如何使用其值的类型?

TypeScript类型不匹配:在返回类型中处理已经声明的Promise Wrapper

动态调用类型化函数

在排版修饰器中推断方法响应类型

在列表的指令中使用intersectionObservable隐藏按钮

不带其他属性的精确函数返回类型

如何获取受类型脚本泛型约束的有效输入参数

在类型脚本中将泛型字符串数组转换为字符串字母并集

如何使这种一对一关系在旧表上起作用?

为什么上下文类型在`fn|curred(Fn)`的联合中不起作用?

界面中数组中的混合类型导致打字错误

Cypress-验证别名的存在或将别名中的文本与';if';语句中的字符串进行比较

如何键入对象转换器

使用强制转换编写打字函数的惯用方法

可以用任意类型实例化,该类型可能与

是否使用类型将方法动态添加到类?

React HashRouter,单击导航栏时页面重新加载出现问题

有没有办法从不同长度的元组的联合中提取带有类型的最后一个元素?

错误:仅允许在‘使用服务器’文件中导出异步函数

Next.JS-13(应用程序路由)中发现无效的中间件