使用infer关键字创建反向类型查找?



这是我所拥有的,我有各种类型,并且我有这种类型的字符串表示:

type PossibleValueTypes = Color | number | Position;
type PossibleValueTypesAsString = "color" | "number" | "position";
type ValueTypeMap = {
"color" : Color; 
"number" : number; 
"position" : Position; 
}; 

现在,给出一个给定的字符串表示,返回值类型很容易,例如;


function generateRandomValueOfType<T extends PossibleValueTypesAsString>(type: T) : ValueTypeMap[T] {
if (type === 'color') {
return {
r: 1, 
g: 1, 
b: 1, 
a: 1, 
} as ValueTypeMap[T]
}
if (type === "position") {
return {
x:1, 
y: 1
} as ValueTypeMap[T]
}
if (type === "number") {
return 1 as ValueTypeMap[T]; 
}
throw new Error ("We shouldn't have got here"); 
}; 

const a: Position = generateRandomValueOfType("position"); 
const b: number = generateRandomValueOfType("position"); // Expected error!

现在的问题是-如果我想做相反的事情,即-给定一个值类型,确定字符串表示。

我能想到的最好的方法是使用链式条件语句,比如:

type ReverseValueTypeLookup<T extends PossibleValueTypes>  = T extends Color ? "color" : T extends number ? "number" : T extends Position ? "position": never; 
function hasAValueAcceptingCallback<T extends PossibleValueTypes> (callback: (value: T) => void, valueTypeAsString: ReverseValueTypeLookup<T>)  {
const value = generateRandomValueOfType(valueTypeAsString); 
//Argument of type 'ValueTypeMap[ReverseValueTypeLookup<T>]' is not assignable to parameter of type 'T'.
//'ValueTypeMap[ReverseValueTypeLookup<T>]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'PossibleValueTypes'.
callback(value);
}



但这在我给出的例子中实际上不起作用

有没有一种更简洁的方法来实现我在这里想要做的两件事?

TS操场

一个相当冗长但有效的解决方案是…

type ReverseValueTypeLookup<T extends ValueTypeMap[keyof ValueTypeMap]> = {
[x in keyof ValueTypeMap]: ValueTypeMap[x] extends T ? x : never;
}[keyof ValueTypeMap];
// exclude key x when ValueTypeMap[x] is not assignable to T, and then get the types of values
type C = ReverseValueTypeLookup<Color>; // type 'color'
type N = ReverseValueTypeLookup<number>; // type 'number'

如果您仍然无法区分Color | number | Position的类型,请使用类型窄化,如…

var data: Color | number | Position;
if (typeof data === 'number') {
// data is number
} else if ('r' in data) {
// data is Color
} else if ('x' in data) {
// data is Position
}

相关内容

  • 没有找到相关文章

最新更新