使用 infer 关键字创建反向类型查找? [复制]

Posted

技术标签:

【中文标题】使用 infer 关键字创建反向类型查找? [复制]【英文标题】:Create a reverse type look up using the infer keyword? [duplicate] 【发布时间】:2021-10-25 05:23:24 【问题描述】:

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

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 Playground

【问题讨论】:

如果我在这里将answer 翻译成另一个问题,我会得到this,但请注意,在这个答案和你接受的答案中,如果没有类型断言,你就不能调用callback(value);编译器只是不够聪明,无法看到这将是安全的。但是您提出的问题似乎是“进行反向类型查找”而不是“当T 是一些未指定的泛型时,让编译器相信Fwd&lt;Rev&lt;T&gt;&gt; 等同于T”,所以我不会担心关于那个。 【参考方案1】:

一个相当冗长但可行的解决方案是......

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

【讨论】:

以上是关于使用 infer 关键字创建反向类型查找? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

typescript 中的 infer 关键字的理解

TypeScript `infer` 关键字

DNS服务的配置与管理---配置正向查找区域

日志查找到第一个关键字后反向查找第二个关键字

白话typescript中的extends和infer(含vue3的UnwrapRef)

白话typescript中的extends和infer(含vue3的UnwrapRef)