javascript - Typescript 拒绝不符合接口(interface)的属性

标签 javascript typescript

我有一个 API Controller ,它采用这样的主体参数

insertUser(@Body() user: IUser) {}

但是问题是我可以发布一个包含比 IUser 定义的更多属性的对象。

确保 user 严格遵守类型或克隆它仅保留接口(interface) IUser` 中定义的内容的最简单、最干净的方法是什么?

最佳答案

我的回答与框架无关。您询问如何强制 TS 不允许传递具有附加字段的类型的值,这意味着我们希望该类型具有独占行为,您具有相同的属性,否则您不允许。

首先,这种行为在类型级别上没有好处,就好像给定值具有我们需要的字段,那么其他字段对我们来说应该不重要。另一件事是,即使我们可以对类型进行编译时检查,如果您的数据来自 API,那么您需要在运行时级别进行验证。

首先是类型级别独占类型行为实现:

type IUser = {
  name: string;
  lastname: string;
}
// utility type to enforce exlusive type
type OnlyExistingFields<Champion, Pretendent> = {
  [K in keyof Pretendent]: K extends keyof Champion ? Pretendent[K] : never
}

// example type with more fields
type IMoreUser = IUser & {
  age: number;
}
// instance of correct type
const u1: IUser = {
  lastname: '',
  name: ''
}
// instance of type with more fields
const u2: IMoreUser = {
  lastname: '',
  name: '',
  age: 12
}
// below type declaration of exlusive function
declare function insertUser<U extends OnlyExistingFields<IUser, U>>(user: U): void

// usage:
insertUser(u1) // 👍 correct type is the same
insertUser(u2) // 🔴  error type has more fields

上面是完全类型级别检查,我们只能传递特定类型的参数,不允许传递该类型的任何超集。

正如我所说,上面的解决方案只是类型级别,实际上,如果对象在运行时有或不需要接口(interface),则无法在类型级别强制执行,一切都只是假设。

也就是说,我们还需要运行时转换器才能删除所有不需要的字段。考虑这样的转换器:

// converts object with probably more fields to object with only wanted fields
function toIUser<T extends IUser>(a: T): IUser {
    return {
      name: a.name,
      lastname: a.lastname
    }
}
const u3 = toIUser(u2); // u3 is IUser and also in runtime has only IUser fields

关于javascript - Typescript 拒绝不符合接口(interface)的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60606650/

相关文章:

javascript - 在 native react 中加密SD卡中的视频文件

javascript - 使用finally() 正确构建Javascript Promise

javascript - 收到错误 : Argument of type '() => () => boolean' is not assignable to parameter of type 'EffectCallback'

typescript - 类型安全的 useDispatch 和 redux-thunk

angular - 带 JSON 的条件列表

javascript - 具有 'as' 属性的通用 React TypeScript 组件(能够渲染任何有效的 dom 节点)

javascript - 如果在循环内部使用,则强制将 getter 结果存储在变量中

javascript - Google Charts 不接受格式正确的数组作为行数据

javascript - 在javascript中实现一个将对象转换为字符串的递归函数

Javascript - 悬停时 Bootstrap 下拉菜单打开子菜单的所有菜单级别