【问题标题】:Indexable type - TypeScript可索引类型 - TypeScript
【发布时间】:2021-02-11 16:46:12
【问题描述】:

下面的语法,

interface StringArray {
    [index: number]: string;
}

声明当StringArraynumber 索引时,它将返回string。比如——

let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];

因此,myArray 的类型受限于存储为 string 类型的值,方法是使用类型 StringArray 声明它。 Key(index) 始终是 string 类型,在引擎盖下(JavaScript),尽管提到它为 number


从下面的语法,

class Animal{
  name: string;
}

class Dog extends Animal{
  breed: string;
}

interface NotOkay {
  [x: number]: Animal;
  [x: string]: Dog;   
}
  1. NotOkay 语法状态是什么?

从下面的语法,

interface NumberDictionary {
    [index: string]: number;
    length: number;    // ok, length is a number
    name: string;      // error, the type of 'name' is not a subtype of the indexer
}
  1. NumberDictionary 表示什么?

  1. 为什么这两种语法是错误的? error TS2413 & error: TS2411

【问题讨论】:

  • @betadeveloper 我有一个想法,javascript 在索引之前将索引对象转换为字符串。但是,当该文档说,从数字索引器返回的类型必须是从字符串索引器返回的类型的子类型时,我没有得到。首先,我不懂语法
  • 编译器可以根据索引的类型和值的类型推断出有效的操作。在 NotOkay 对象 o 的情况下,该对象具有数字 1 作为键和 Animal 作为其值,它在查找时将允许访问 Animal 而不是 Dog i>o 与字符串 "1" 。问题是 Animals 中缺少属性 breed ,因此 o["1"].breed 将是无效操作。如果 number 索引是 Dog 的子类型,那么操作就可以了,因为子类型从 Dog继承了 breed >.
  • 这种类型检查并不能完全防止运行时错误。即使 o 中未定义“nil”属性,它也会愉快地编译 o["nil"].breed,并且在尝试访问其品种时会导致 TypeError .

标签: javascript typescript duck-typing


【解决方案1】:

(正如@betadeveloper 指出的那样,示例取自https://www.typescriptlang.org/docs/handbook/interfaces.html 的打字稿文档)

1+3) 文档的重点是该声明不一致。

声明似乎表明此代码有效:

let no: NotOkay

function byString(key: string): Dog {
   return no[key]
}

function byNumber(key: number): Animal {
   return no[key]
}

但问题是查找例如no[0]no['0'] 是一回事(这就是 JavaScript 的工作原理)。所以byString('0')实际上只会产生动物,不一定是狗。

所以为了防止上面的代码——看起来正确但实际上对于某些字符串键(那些恰好是字符串形式的数字)是错误的——TypeScript 不允许声明。

2+3) [index: string]: number; 表示你可以使用任何字符串作为NumberDictionary 的索引,你会得到一个数字。

另一方面,name: string; 表示属性name 是一个字符串。但是属性也可以作为索引访问,例如做的时候

let nd: NumberDictionary

let a = nd['name']
let b = nd.name

a 和 b 的意思完全相同,但第一个声明似乎说 a 是一个数字,而第二个声明似乎说 b 是一个字符串。这是一个矛盾,因此也不允许这种声明。

【讨论】:

    猜你喜欢
    • 2020-08-01
    • 2021-11-20
    • 2021-04-05
    • 1970-01-01
    • 2019-08-10
    • 2021-02-22
    • 2021-12-30
    • 2020-01-27
    相关资源
    最近更新 更多