打字稿:防止分配具有比目标接口中指定的更多属性的对象 [英] Typescript: prevent assignment of object with more properties than is specified in target interface

查看:22
本文介绍了打字稿:防止分配具有比目标接口中指定的更多属性的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个典型的用户"对象,它具有常用的用户名、电子邮件、密码等属性.我想创建和管理一个对象,该对象是此类用户的真正子集",并保证不包含密码.这是一个粗略的方法:

Say I have a typical 'user' object with the usual username, email, password, etc. properties. I want to create and manage an object that is a bona fide 'subset' of such a user with assurances that the password is NOT included. Here's a rough approach:

interface IUserSansPassword {
    username: string;
    email: string;
}

class UserSansPassword implements IUserSansPassword { ... }

interface IUser extends IUserSansPassword {
    password: string;
}

class User implements IUser { ... }

在尝试创建 IUserSansPassword 类型的对象时,我预计会出现以下错误:

In trying to create an object of type IUserSansPassword, I expected the following to error:

const userSansPassword: UserSansPassword = new User(); // No TS Error †††

但是,我没有收到 TS 错误,因为令我惊讶的是,TS 并没有禁止分配具有已经建立的额外"属性的对象.这是令人惊讶的,因为如果我尝试直接使用额外的属性进行定义,我会得到一个错误:

However, I don't get a TS error because, to my surprise, TS doesn't prohibit assigning objects with already established 'extra' properties. This is surprising since I would get an error if I tried to define directly with the extra property like so:

const userSansPassword: IUserSansPassword = {
    username: 'jake',
    email: 'jake@snake.com',
    password: '' // TS Error ***
}

我的问题总结:

  1. 为什么 TS 会这样?允许分配给具有过多属性的类型是不是很糟糕(因此为什么在上面的 *** 中出现错误)?

  1. Why does TS behave this way? Isn't it bad to allow assignment to a type with excess properties (hence why you get an error in *** above)?

是否有我可以采用的 TS 设置或技术来使 TS 在上面的 ††† 中出错?

Is there a TS setting or technique I can employ to get TS to error in ††† above?

推荐答案

这里的其他答案基本上是正确的:TypeScript 中的类型通常是开放/可扩展的,并且总是可以添加属性;也就是说,它们不是只允许存在已知属性的确切类型.TypeScript 通常并不真正支持精确类型,尽管它确实通过 多余的财产检查,正如您所注意到的.

The other answers here are essentially correct: types in TypeScript are generally open/extendable and can always have properties added; that is, they are not exact types in which only known properties are allowed to exist. TypeScript doesn't really support exact types in general, although it does treat the types of freshly created object literals as exact types via excess property checks, as you've noticed.

如果您真的想禁止 TypeScript 中的某个类型的特定属性键,您可以通过将属性设为可选并将其类型设为 neverundefined 来实现:

If you really want to forbid a particular property key from a type in TypeScript, you can do this by making the property optional and have its type be never or undefined:

interface IUserSansPassword {
  username: string;
  email: string;
  password?: never; // cannot have a password
}

declare class UserSansPassword implements IUserSansPassword {
  username: string;
  email: string;
  password?: never; // need to declare this also
}

现在 UserSansPassword 已知没有具有定义的 password 属性.当然现在下面是一个错误:

Now UserSansPassword is known not to have a defined password property. Of course now the following is an error:

interface IUser extends IUserSansPassword { // error! 
// Types of property "password" are incompatible
  password: string;
}

你不能通过添加密码来扩展 IUserSansPassword...如果 A extends B 那么你总是可以使用 A 实例,其中需要 B 实例.您可以做的是扩展相关类型,您的原始 IUserSansPassword,可以使用 Omit 辅助类型:

You can't extend IUserSansPassword by adding a password... if A extends B then you can always use an A instance where a B instance is expected. What you can do is extend a related type, your original IUserSansPassword, which can be computed using the Omit helper type:

interface IUser extends Omit<IUserSansPassword, "password"> {
  password: string;
}

declare class User implements IUser {
  username: string;
  email: string;
  password: string;
}

然后是您所期望的错误:

And then the following is an error like you expect:

const userSansPassword: UserSansPassword = new User();
// error, mismatch on "password" prop

好的,希望有帮助;祝你好运!

Okay, hope that helps; good luck!

链接到代码

这篇关于打字稿:防止分配具有比目标接口中指定的更多属性的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆