Reputation: 10909
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
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