使用属性声明TypeScript函数

vktxenjb  于 2023-04-22  发布在  TypeScript
关注(0)|答案(3)|浏览(142)

我正在编写a library,我想将其移植到TypeScript。
目前它看起来像这样:

文件 index.js

const is = value => {
    // ... Do some returns here
}

is.number = x => typeof x === 'number'
is.bla = x => typeof x === 'bla'

等等。
我写了一个接口来描述is和它的所有方法。

type TypeQueryMethod = (val: any) => boolean;

interface Is {
    (val: any): string;
    undefined: TypeQueryMethod;
    null: TypeQueryMethod;
    // ...
}

当我尝试将is标记为以下类型时:const is: Is = value => ...
它抛出一个错误:

Type '(value: any) => string' is not assignable to type 'Is'.
Property 'undefined' is missing in type '(value: any) => string'.

这是有意义的,因为对象的声明是拆分的。
如何构造这样一个既是方法又有方法的对象?

blmhpbnm

blmhpbnm1#

更新TypeScript 3.1+
TypeScript 3.1引入了对函数声明属性的支持,允许您以开始的方式执行此操作:

const is: Is = (val: any) => typeof val; // okay
is.undefined = (val: any) => typeof val === 'undefined'; 
is.null = (val: any) => (val === null)

对于TypeScript 3.1之前的版本:
如果你想让类型检查器满意,你可以使用Object.assign()返回一个完整的Is对象,而不需要分阶段构建它:

const is: Is = Object.assign(
  (val: any) => typeof val,
  {
    undefined: (val: any) => typeof val === 'undefined',
    null: (val: any) => (val === null)
    // ...
  }
);

当然,如果你不想改变代码的结构,那么你可以像@Saravana建议的那样,使用type assertion来通知类型检查器is肯定是Is,即使在你完成构建之前,它在技术上不是一个。
无论哪种方式都可以,但我更喜欢Object.assign()方法,因为如果你忽略了实现某些东西,类型检查器会警告你:

// error, "undefined" is missing
const is: Is = Object.assign(
  (val: any) => typeof val,
  {
    null: (val: any) => (val === null)
    // ...
  }
);

而类型Assert方法将不会:

const is = ((val: any) => typeof val) as any as Is;
is.null = (val) => val === null;
// no error

而类型Assert方法不会。这取决于你。
Playground链接到代码

webghufk

webghufk2#

你不能同时实现一个函数和它的属性。你可以先定义一个函数,然后Assert它到Is,然后定义剩下的方法:

const is = ((val: any) => typeof (val)) as any as Is;

is.null = (val) => true;
is.undefined = (val) => true;

或者使用工厂函数创建Is

function createIs(): Is {
    const is = ((val: any) => {
        return "";
    }) as Is;
    is.null = (val) => true;
    is.undefined= (val) => true;
    return is;
}

const is: Is = createIs();
aelbi1ox

aelbi1ox3#

你所需要做的就是将属性设置为可选的:

type TypeQueryMethod = (val: any) => boolean;

interface Is {
    (val: any): string;
    undefined?: TypeQueryMethod;
    null?: TypeQueryMethod;
    ...
}

现在你可以安全地将它定义为Is

const is: Is = value => ...

相关问题