Description
TypeScript Version: 3.7-beta
Search Terms: conditional types generic problem
Note: I'll say "reverse type" a lot in this issue. In such context, the reversed type of a number is string, and the reversed type of a string is a number.
I have the following code:
type Id = string | number;
type ObjectId<T extends Id> = {
id: T;
};
type ValidObjectId = ObjectId<string> | ObjectId<number>
type ReverseId<T extends ValidObjectId> = T['id'] extends number ? string : number;
function encodeObjectId<T extends ObjectId<number>>(
obj: T
): ReverseId<T> {
const id = obj.id;
// Why does the following does not accept a string type?
// As it's the reverse of type number, because of the `ReverseId` type, it should be working.
return id.toString();
}
In it, I have the type ReverseId
, which converts the type of the id
property. For example, if the given object id
property has a number
type, it will return string
; and if the given object's id
property has a string
type, the number
type will be returned.
And that actually works:
type Id = string | number;
type ObjectId<T extends Id> = {
id: T;
};
type ValidObjectId = ObjectId<string> | ObjectId<number>
type ReverseId<T extends ValidObjectId> = T['id'] extends number ? string : number;
// The `t` constant has a `number` type, which is the "reverse" of the `string`
// type, used in the given `ObjectId`.
const t: ReverseId<ObjectId<string>> = 1;
The problem is: when the ObjectId
comes from a generic, as we saw in the encodeObjectId
function in the first example, the type does not work.
I think that this is a problem, because it work when the ObjectId
type does not come from a generic, and don't work when this type comes from a generic.