Christian Sauer
Christian Sauer

Reputation: 10909

How to allow for return type

Consider this code:

type deviceStatusType = string | boolean | number | undefined;

class A {
 protected constructor() {
        this.status = {
        "a": 1,
        "b": "b"
        }
    }

    getDeviceStatus<T extends deviceStatusType>(arg: deviceStatusType,  code: string): T {
        const status = this.status[code];

        let actualType = typeof status;
        if (actualType !== arg){
            throw new Error(`mode should be a ${arg} but is: ${typeof(status)}`)
        }

        return status;
    }
}

I get the error

TS2322: Type 'string | number | boolean' is not assignable to type 'T'.   'string | number | boolean' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'deviceStatusType'.     Type 'string' is not assignable to type 'T'.       'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'deviceStatusType'.

on return status - but I really want to be able to move the typecheck into this function since that reduces the number of times I have to check the type to one place.

Upvotes: 0

Views: 43

Answers (1)

hansmaad
hansmaad

Reputation: 18915

As you already did the explicite type check, you could just declare status as any which you can assign to return value of T. If you want you can slightly improve it to

class A {
  getDeviceStatus<T extends deviceStatusType>(arg: T, code: string): T {
    const status = this.status[code];
    if (isType(status, arg)) {
        return status;
    }
    throw new Error(`mode should be a ${arg} but is: ${typeof(status)}`);
  }
}

function isType<T extends deviceStatusType>(actual: any, arg: T): actual is T {
  return typeof actual === arg;
}

Upvotes: 2

Related Questions