为什么 TypeScript 有时只能通过字符串索引对象
Why can TypeScript only Sometimes Index an Object by a String
为什么当字符串是常量或简单的字符串变量时 TypeScript 可以通过字符串索引类型化对象,但如果字符串是从数组中提取出来的,它就无法通过字符串索引类型化对象
也就是考虑下面的代码
class Foo {
public bar: string = 'hello';
public test() {
// this works
console.log(this['bar'])
// this also works
const index = 'bar';
console.log(this[index])
// in both cases above I have successfully used
// a string as an index for my type Foo
// However, this doesn't work
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
// Nor does this
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
// when looping over an array of string and trying to use the
// string to index the object, I get the following error
// why.ts:20:25 - error TS7053: Element implicitly has an 'any'
// type because expression of type 'string' can't be used to
// index type 'Foo'.
}
}
const foo = new Foo;
foo.test()
class Foo {
public bar: string = 'hello';
public test() {
// this works
console.log(this['bar'])
// this also works
const index = 'bar';
console.log(this[index])
// in both cases above I have successfully used
// a string as an index for my type Foo
// However, this doesn't work
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
// Nor does this
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
// when looping over an array of string and trying to use the
// string to index the object, I get the following error
// why.ts:20:25 - error TS7053: Element implicitly has an 'any'
// type because expression of type 'string' can't be used to
// index type 'Foo'.
}
}
const foo = new Foo;
foo.test()
这两个都有效。
console.log(this['bar'])
//...
const index = 'bar';
console.log(this[index])
TypeScript 能够通过字符串为我的对象编制索引。
但是,后面的例子中我在字符串数组上循环
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
不会 run/compile。我收到以下错误。
why.ts:42:17 - error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Foo'.
No index signature with a parameter of type 'string' was found on type 'Foo'.
42 console.log(foo[value])
所以这个错误信息——expression of type 'string' can't be used to index type 'Foo' seems to 运行 counter我的前两个例子。
这是怎么回事?帮助一个可怜的动态语言程序员理解 TypeScript 试图告诉我什么。一个示例的加分点,它实际上允许我迭代一个字符串数组并将一个字符串用作对象索引。
答案很简单,如果typescript可以证明访问是安全的,那么索引是允许的。
当你写 this['bar']
时,打字稿会看到字符串文字,它可以简单地检查 this
是否有 属性 bar
当你写const index = 'bar';
时你可能认为index
的类型是string
但实际上不是,index
的类型是string literal type 'bar'
,所以打字稿会知道 index
中唯一可能的值是 'bar'
。由于 index
只能保留 bar,typescript 可以通过检查 this
是否具有 属性 bar
来检查访问 this[index]
是否有效
当您编写 const props:string[]
时,打字稿不会对 props
进行任何其他推断,它是 string
的数组。这意味着当您访问 this[prop]
时,打字稿需要确保 this
可以被任何 string
索引,因为它没有索引签名,所以它不是,因此访问会引发错误.如果您使用 as const
让 ts 推断数组的文字类型而不是 string
并删除显式注释,您将能够执行索引访问:
const props = ['bar'] as const
for(const [key,value] of props.entries()) {
console.log(value);
console.log(this[value])//ok
}
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
如果您确定 prop
是 this
的键,您也可以使用类型断言:
const props = ['bar']
for(const [key,value] of props.entries()) {
console.log(this[value as keyof this])
}
或者,如果你真的想变得很花哨,你可以使用自定义类型保护或自定义类型断言,但这在这里似乎有点过分了。
为什么当字符串是常量或简单的字符串变量时 TypeScript 可以通过字符串索引类型化对象,但如果字符串是从数组中提取出来的,它就无法通过字符串索引类型化对象
也就是考虑下面的代码
class Foo {
public bar: string = 'hello';
public test() {
// this works
console.log(this['bar'])
// this also works
const index = 'bar';
console.log(this[index])
// in both cases above I have successfully used
// a string as an index for my type Foo
// However, this doesn't work
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
// Nor does this
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
// when looping over an array of string and trying to use the
// string to index the object, I get the following error
// why.ts:20:25 - error TS7053: Element implicitly has an 'any'
// type because expression of type 'string' can't be used to
// index type 'Foo'.
}
}
const foo = new Foo;
foo.test()
class Foo {
public bar: string = 'hello';
public test() {
// this works
console.log(this['bar'])
// this also works
const index = 'bar';
console.log(this[index])
// in both cases above I have successfully used
// a string as an index for my type Foo
// However, this doesn't work
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
// Nor does this
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
// when looping over an array of string and trying to use the
// string to index the object, I get the following error
// why.ts:20:25 - error TS7053: Element implicitly has an 'any'
// type because expression of type 'string' can't be used to
// index type 'Foo'.
}
}
const foo = new Foo;
foo.test()
这两个都有效。
console.log(this['bar'])
//...
const index = 'bar';
console.log(this[index])
TypeScript 能够通过字符串为我的对象编制索引。
但是,后面的例子中我在字符串数组上循环
const props:string[] = ['bar']
for(const [key,value] of props.entries()) {
console.log(value); // prints 'bar' to terminal/console
console.log(this[value])
}
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
不会 run/compile。我收到以下错误。
why.ts:42:17 - error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Foo'.
No index signature with a parameter of type 'string' was found on type 'Foo'.
42 console.log(foo[value])
所以这个错误信息——expression of type 'string' can't be used to index type 'Foo' seems to 运行 counter我的前两个例子。
这是怎么回事?帮助一个可怜的动态语言程序员理解 TypeScript 试图告诉我什么。一个示例的加分点,它实际上允许我迭代一个字符串数组并将一个字符串用作对象索引。
答案很简单,如果typescript可以证明访问是安全的,那么索引是允许的。
当你写 this['bar']
时,打字稿会看到字符串文字,它可以简单地检查 this
是否有 属性 bar
当你写const index = 'bar';
时你可能认为index
的类型是string
但实际上不是,index
的类型是string literal type 'bar'
,所以打字稿会知道 index
中唯一可能的值是 'bar'
。由于 index
只能保留 bar,typescript 可以通过检查 this
是否具有 属性 bar
this[index]
是否有效
当您编写 const props:string[]
时,打字稿不会对 props
进行任何其他推断,它是 string
的数组。这意味着当您访问 this[prop]
时,打字稿需要确保 this
可以被任何 string
索引,因为它没有索引签名,所以它不是,因此访问会引发错误.如果您使用 as const
让 ts 推断数组的文字类型而不是 string
并删除显式注释,您将能够执行索引访问:
const props = ['bar'] as const
for(const [key,value] of props.entries()) {
console.log(value);
console.log(this[value])//ok
}
for(let i=0;i<props.length;i++) {
console.log(this[props[i]])
}
如果您确定 prop
是 this
的键,您也可以使用类型断言:
const props = ['bar']
for(const [key,value] of props.entries()) {
console.log(this[value as keyof this])
}
或者,如果你真的想变得很花哨,你可以使用自定义类型保护或自定义类型断言,但这在这里似乎有点过分了。