Typescript object indexer and key that doesn't match indexer type

前端 未结 2 1030
灰色年华
灰色年华 2021-01-20 18:34

The Typescript docs show the following example:

interface NumberDictionary {
    [index: string]: number;
    length: number;    // ok, length is a number
           


        
相关标签:
2条回答
  • 2021-01-20 19:21

    Like this:

    interface NumberDictionary {
        [index: string]: number | string;
        length: number;
        name: string;
    }
    
    0 讨论(0)
  • 2021-01-20 19:33

    The problem is that such a type is inherently inconsistent. Consider the following code:

    let prop = Math.random() > 0.5 ? "name" : "other"
    let dic: NumberDictionary;
    let value = dic[prop] // typed as number but could end up as string at run-time
    

    The index definition tells us number but we might end up with string at runtime.

    The honest thing to do is make the index signature return number | string.

    interface NumberDictionary {
        [index: string]: number | string;
        length: number;
        name: string;
    }
    let prop = Math.random() > 0.5 ? "name" : "other"
    let dic: NumberDictionary;
    let value = dic[prop] // typed as number | string we need a type guard to tell teh difference
    

    The honest solution might not always be practical, and, being fully aware of the dangers, you can define an intersection type that will let you get away with the inconsistency:

    type NumberDictionary = {
      [index: string]: number;
    } & {
      length: number;    
      name: string;
    }
    
    let prop = Math.random() > 0.5 ? "neverName" : "other"
    let dic: NumberDictionary = {
      name: "",
      length: 1
    } as NumberDictionary; // type assertion necessary, ts will still complain here about the inconsistentcy 
    let value = dic[prop] // typed as number, hope everyone avoids passing in name
    
    0 讨论(0)
提交回复
热议问题