case generic type parameters for primitives

Background

I have the following generic class in TypeScript, that accepts a constructor function and a callback as its constructor arguments:

class InputDataPort<T> {
    constructor(type: new (...args: any[]) => T, listener?: (data: T) => void);
    onUpdate(listener?: (data: T) => void);

    // ... lots of other methods depending on the generic type parameter 'T'
}
var dataPortA = new InputDataPort(Array, array => console.log(array)); // T: Array
var dataPortB = new InputDataPort(Date, array => console.log(array)); // T: Date
...

Here, I'm essentially defining the generic type parameter as a constructor argument. The reason it's this way is that I need to know the generic type at runtime, and this approach enables that.

Problem

However, I'm running into a problem with primitive types. Basically, when I do the following:

var dataPortN = new InputDataPort(Number, num => console.log(num));

num is of type Number , and the TypeScript compiler does not allow assigning a Number to a number (obviously, number cannot be specified as the argument to type ):

var myNum: number;

// ERROR: 'number' is a primitive, but 'Number' is a wrapper object ...
var dataPortM = new InputDataPort(Number, num => myNum = num);

In this case (as well as in the case of other primitive/wrapper types), I would like to use the corresponding primitive types as the generic type parameter T .

Essentially, I'm looking for the following type definition:

  • if T is Number, then number
  • else if T is String, then string
  • else if T is Boolean, then boolean
  • else T as-is
  • To the best of my knowledge, method overloading is not sufficient here, as it doesn't provide a class-level generic type.


    Although I'm not sure if the requirements described in the question are possible at all, one solid workaround is specializing the base InputDataPort class for each primitive type.

    For example, to support number , one can do:

    class InputNumberDataPort extends InputDataPort<number> {
        constructor(listener?: (data: number) => void) {
            super(Number as any, listener);
        }
    }
    

    Same for the rest with InputStringDataPort , InputBooleanDataPort , and so on. This approach will provide the correct generic types for the TypeScript compiler, and also the correct corresponding constructor references at runtime.

    链接地址: http://www.djcxy.com/p/43158.html

    上一篇: Haskell词法布局规则的实现

    下一篇: 用于基元的案例泛型类型参数