简体   繁体   English

Joi 类型的声明合并

[英]Declaration merging for Joi types

I want to narrow the type property of the ValidationErrorItem from Joi using declaration merging.我想使用声明合并来缩小JoiValidationErrorItemtype属性。

The interface in Joi looks like this: Joi 中的界面如下所示:

declare namespace Joi {
   interface ValidationErrorItem {
        message: string;
        path: Array<string | number>;
        type: string;
        context?: Context;
    }
}

My index.d.ts in src/types looks like this:我在src/types中的index.d.ts如下所示:

import { Context } from 'joi'

declare namespace Joi {
  type ValidationErrorItemType = 'any.required' | 'date.format'
  export interface ValidationErrorItem {
    message: string
    path: Array<string | number>
    type: ValidationErrorItemType
    context?: Context
  }
}

This is my include in tsconfig.json :这是我在tsconfig.jsoninclude的内容:

 "include": ["src/**/*", "types/types.d.ts"]

However, VS Code still shows type to be of type string instead of ValidationErrorItem and when using it in a switch statement I can still use any string without getting compiler warnings.但是,VS Code 仍然显示type为 string 而不是ValidationErrorItem类型,并且在switch语句中使用它时,我仍然可以使用任何字符串而不会收到编译器警告。

Update更新

This is my tsconfig.json这是我的tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "declaration": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "*": ["node_modules/*", "src/types/*"]
    }
  },
  "include": ["src/**/*", "types/joi.ts"]
}

This is my joi.d.ts based on the answer from @tymzap:这是我的joi.d.ts基于@tymzap 的回答:

declare module 'joi' {
  // full path to joi typings is used to avoid circular import path
  import type { Context } from 'joi/lib/index'
  export { default } from 'joi/lib/index'

  type ValidationErrorItemType = 'any.required' | 'date.format'

  export type ValidationErrorItem = {
    message: string
    path: Array<string | number>
    type: ValidationErrorItemType
    context?: Context
  }
}

This is my sample usage:这是我的示例用法:

error.details.map((i) => {
    const x: ValidationErrorItem = i as ValidationErrorItem
    switch (x.type) {
      case 'any.required':
        break

      default:
        break
    }
  })

You can't narrow the type using interface merging.您不能使用接口合并来缩小类型。 This operation extends types, not overrides them.此操作扩展类型,而不是覆盖它们。 Extending ValidationErrorItemType with string gives ValidationErrorItemType | stringstring扩展ValidationErrorItemType给出ValidationErrorItemType | string ValidationErrorItemType | string , that's why you still can use any string . ValidationErrorItemType | string ,这就是为什么你仍然可以使用任何string

To achieve this you can redeclare Joi module.为此,您可以重新声明 Joi 模块。 Modify the type to your needs and export it after reexporting original Joi typings.根据您的需要修改类型并在重新导出原始 Joi 类型后将其导出。

joi.d.ts: joi.d.ts:

declare module 'joi' {
  // full path to joi typings is used to avoid circular import path
  import type { Context } from 'joi/lib/index';
  export * from 'joi/lib/index';
  export { default } from 'joi/lib/index';

  type ValidationErrorItemType = 'any.required' | 'date.format';

  export type ValidationErrorItem = {
    message: string;
    path: Array<string | number>;
    type: ValidationErrorItemType;
    context?: Context;
  }
}

Test:测试:

import type { ValidationErrorItem } from 'joi';

const test: ValidationErrorItem = {
  // error: Type '"wrong.type"' is not assignable to type 'ValidationErrorItemType'.
  type: 'wrong.type',
  message: 'dummy message',
  path: ['dummy-path'],
};

This way you can effectively override given type from library, without merging with its original signature.这样,您可以有效地覆盖库中的给定类型,而无需与其原始签名合并。

Edit: Joi uses old export = syntax, depending on your compiler settings this could lead to errors based on typings flavour incompatibility.编辑:Joi 使用旧的export =语法,这取决于您的编译器设置,这可能会导致基于类型不兼容的错误。 In this case you can add this line to tsconfig:在这种情况下,您可以将此行添加到 tsconfig:

{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM