Home > Blockchain >  Type inference changing from unknown to known type after using method
Type inference changing from unknown to known type after using method

Time:07-05

I have a class with single generic T, where sometimes it may be constructed with a value so T is known, sometimes constructed without a value and so T is unknown. It is tedious to have to specify the type when no value is given where the type may be able to be inferred.

This is boiled down to the exact problem I'm having with a more complicated class where needing T to be not unknown while a value is not held, because it can be held later.

class Foo<T> {
    value:T;

    constructor(value?:T) {
        if(value != null && value != undefined) {
            this.value = value;
        }
    }

    public set(value:T) {
        this.value = value;
    }
}

const fn1 = ():Foo<number> => {
    const foo = new Foo(0); //foo is Foo<number>
    foo.set(1);

    return foo; //No error
}

const fn2 = ():Foo<number> => {
    const foo = new Foo(); //foo is Foo<unknown>
    foo.set(1);
    //unknown accepts number apparently and such there is no type collision
    //However, I want foo to be re-evaluated to be Foo<number>

    return foo; //Error
    //const foo: Foo<unknown>
    //Type 'Foo<unknown>' is not assignable to type 'Foo<number>'.
    //  Type 'unknown' is not assignable to type 'number'.
}

const fn3 = ():Foo<number> => new Foo(); //No error, is inferred as being Foo<number>

Is there something I am missing to allow the generic type to be re-evaluated to be non-unknown?

Alternatively, is there a way for it to never be unknown? Such that if I do new Foo() it will ask for a type to be specified. (Also, it's not the best thing for the job, but Foo<any> can be converted into Foo<number>, so is there a way I could make it such that any is default?)

I am aware that a solution would be just to do new Foo<number>(), however, this feels like something TypeScript should be able to infer and shouldn't need to specify it which does add extra work that may not be necessary.

CodePudding user response:

is there a way I could make it such that any is default?

Yes, simply use a default type for your generic:

class Foo<T = any> {}

Playground Link

CodePudding user response:

Is there something I am missing to allow the generic type to be re-evaluated to be non-unknown?

Unfortunately no, TypeScript never re-evaluates. Inference of a class instance generic type is made only at instantiation:

When a generic class is instantiated with new, its type parameters are inferred the same way as in a function call

  • Related