如何使用“ typeof”从泛型类获取类型?

时间:2019-06-25 09:07:47

标签: typescript

当我在A中声明泛型类a.js并将其导出时,然后,我不知道如何在A中声明类b.js的变量

以下代码: a.js

export let A = function<K extends { value: number }>(DEFAULT_NUMBER){
    return class A<T> {
    test(obj: T, num: number): K {
        return obj.diff(DEFAULT_NUMBER, num);
    };
    };
}(
    // DEFAULT_NUMBER
    1000
);

b.js

import { A } from "a.js";

class B {
    diff(): { value: number } {
        // ...
    }
};

let a: InstanceType<typeof A<B>> = new A();

a.test(new B(), 50);

下面的简单代码:

let A = class<T> {};

class B {};

let a: InstanceType<typeof A<B>>; // throw a syntax error
// or
let a: InstanceType<(typeof A)<B>>; // throw a syntax error
// or
let a: InstanceType<typeof (A<B>)>; // throw a syntax error
// or
let a: (InstanceType<typeof A>)<B>; // throw a syntax error
// or
let a: InstanceType<typeof A>; // correct, but the type of a is `A<unknown>`

我应该如何声明变量a

3 个答案:

答案 0 :(得分:1)

我不认为这有语法。当然,没有语法可以获取具有特定类型参数的泛型函数的返回类型。

一种方法是通过虚拟函数:

let A = class<T> {};

class B {};

let aHelper = () => new A<B>();
let a: ReturnType<typeof aHelper>;

答案 1 :(得分:0)

据我了解,任何 .js 文件中都不应包含类型定义(例如value: number)。相反,它们应该属于 .ts 文件(TypeScript,而不是JavaScript)。

TypeScript 中,如果您具有如下定义的通用类:

export class A<T extends { something: number }> {
    useSomething(obj: T) {
        console.log(obj.something)
    }
}

然后可以像这样使用它:

class B {
    something: number
}
const a = new A<B>()
a.useSomething(new B())

答案 2 :(得分:0)

这两天我一直在考虑这个问题,最后,我找到了答案,代码如下:

type ReplaceItemTypeOf<Target extends any[], NewType, OldType = unknown> = {
    // for each item of the array
    [Key in keyof Target]: (
        // if the type is matched, return NewTypeNewType, otherwise return the origin type of the item value
        OldType extends Target[Key] ? NewType : Target[Key]
    );
};

type NonAnyType<T> = (T & 1 extends 1 ? 1 : 0) extends 1 ? T : never;

type InstanceTypeOfGenericRef<GenericRef extends new(...args: any) => any, Type> = {
    // for each property
    [Key in keyof InstanceType<GenericRef>]: (
        // if the type is matched unknown type or empty object type
        {} extends (
            // if property is a method
            InstanceType<GenericRef>[Key] extends (...args: any) => infer Result ?
                // if type of Result is any return never, otherwise return the origin type of Result
                NonAnyType<Result> :
                // if type of the property value is any return never, otherwise return the origin type of the property value
                NonAnyType<InstanceType<GenericRef>[Key]>
        ) ?
            (
                // if property is a method, and type has matched
                InstanceType<GenericRef>[Key] extends (...args: infer Args) => infer Result ?
                    // return a new method interface which has replaced argument types
                    (...args: ReplaceItemTypeOf<Args, Type>) => Type :
                    // if not a method, return Type
                    Type
            ) :
            (
                // if property is a method and type has not matched
                InstanceType<GenericRef>[Key] extends (...args: infer Args) => infer Result ?
                    // return a new method interface which has replaced argument types
                    (...args: ReplaceItemTypeOf<Args, Type>) => Result :
                    // return origin type of the property value
                    InstanceType<GenericRef>[Key]
            )
    );
};

let A = class A<T> {
    set(value: T): T {
        return value;
    }
}

let a: InstanceTypeOfGenericRef<typeof A, string>;

a.set("123");

下面的屏幕截图: enter image description here