Тернарный оператор действительно не очень подходит для универсальных типов:
type TriviallyA<T extends DataType> =
T extends any ? A : A;
function GetData<T extends 'a' = 'a'>(dataType: T): TriviallyA<T> {
return new A(); // Error: Type 'A' is not assignable to type 'TriviallyA<T>'
}
Тем не менее, дженерики хорошо работают с поиском по атрибутам, поэтому вы можете определить интерфейс для сопоставления строк с определенными типами, тогда вы можете использовать keyof
и поиск по атрибутам, чтобы действовать как TData
:
interface DataTypeMapping {
a: A;
b: B;
}
type DataType = keyof DataTypeMapping;
type TData<T extends DataType> = DataTypeMapping[T];
function GetData<T extends DataType>(dataType: T): TData<T> {
// now expected return type is A | B so this is valid!
if (dataType === 'a') {
return new A();
} else if (dataType === 'b') {
return new B();
}
}