How to extend a module from npm using TypeScript?

自古美人都是妖i 提交于 2021-02-07 13:25:43

问题


I'm using joi and @types/joi with TypeScript. Joi has an extend method which allows extending joi by returning a new instance without modifying original joi library. I created an extended instance with it.

To create definition for this extended instance, I tried Module Augmentation as described here using code below:

declare module 'joi' {
  // Add a new Schema type which has noChildren() method.
  interface CustomSchema extends ObjectSchema {
    noChildren(): this;
  }
}

However, as expected, this modifies original definition by augmenting it. What I want is to create definitions for the extended instance which inherits everything from original without modifying it.

Also extended Joi is created as below:

import * as Joi from 'joi';
const JoiExtended = Joi.extend({...some implementation...})
// How to export?
// export * from 'Joi' ---> In this case, original non-extended Joi is exported
// export default JoiExtended ---> Imported `Joi` reports: Cannot find namespace 'Joi'
  1. How can I create extended definitions?
  2. How to export extended Joi?

P.S. I'm learning TypeScript and searched for an answer for this question but couldn't find an answer, maybe, because I'm not accustomed to typescript terminology and search for wrong terms.


回答1:


Joi.extend returns a new instance of the joi module for which you can use the exported Root type.

You'll need to create an interface that extends Joi.Root and another that extends the base joi type that you're extending. You can simply export your custom joi instance like you would any other object.

Below is an example using the round() and dividable() rules from the API Documentation examples on extend().

import * as Joi from 'joi';

interface ExtendedNumberSchema extends Joi.NumberSchema {
    round(): this;
    dividable(num: number): this;
}

interface ExtendedJoi extends Joi.Root {
    number(): ExtendedNumberSchema;
}

const customJoi: ExtendedJoi = Joi.extend((joi) => ({
    base: joi.number(),
    name: 'number',
    language: {
        round: 'needs to be a rounded number', // Used below as 'number.round'
        dividable: 'needs to be dividable by {{q}}'
    },
    pre(value, state, options) {

        if (options.convert && this._flags.round) {
            return Math.round(value); // Change the value
        }

        return value; // Keep the value as it was
    },
    rules: [
        {
            name: 'round',
            setup(params) {

                this._flags.round = true; // Set a flag for later use
            },
            validate(params, value, state, options) {

                if (value % 1 !== 0) {
                    // Generate an error, state and options need to be passed
                    return this.createError('number.round', {v: value}, state, options);
                }

                return value; // Everything is OK
            }
        },
        {
            name: 'dividable',
            params: {
                q: joi.alternatives([joi.number().required(), joi.func().ref()])
            },
            validate(params, value, state, options) {

                if (value % params.q !== 0) {
                    // Generate an error, state and options need to be passed, q is used in the language
                    return this.createError('number.dividable', {v: value, q: params.q}, state, options);
                }

                return value; // Everything is OK
            }
        }
    ]
}));


const schema = {
    a: customJoi.number().round().dividable(3)
};

const result = customJoi.validate({a: 4.1}, schema); // will fail because 4 is no divisible by 3

console.log(result);

export = customJoi;


来源:https://stackoverflow.com/questions/47618273/how-to-extend-a-module-from-npm-using-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!