如何在打字稿中检查隐式索引签名类型?

时间:2018-09-04 16:19:06

标签: typescript

我试图弄清楚隐式索引签名的规则是什么,但在此示例中被卡住了:

比方说,我们希望某些返回类型遵循带有索引签名的接口:

interface A { [index: string]: string }
const getA = (): A => {
    return { a : 'a' }
}

这当然是有效的,因为{ a : 'a' }是隐式的any,而any可以隐式地转换为其他所有内容。

让我们说我们对返回的内容有些挑剔,也许是类型为B的某些结果,我们想要隐式映射到接口A:

interface A { [index: string]: string }
interface B { b: string }
const getA = () : A => {
    return { b : 'b' } as B
}

这不起作用,因为接口B被明确定义为没有索引签名。我的想法在这里正确吗? (注意:我真的很想这样做,但是也许不可能)

产生的错误:

  

类型'B'不能分配给类型'A'。缺少索引签名   输入“ B”。

但是,这就是让我感到困惑的地方,对interface A的定义稍松一些可以让我们再次编译:

interface A { [index: string]: any }
interface B { b: string }
const getA = () : A => {
    return { b : 'b' } as B
}

为什么?难道B上仍然缺少索引签名吗?

1 个答案:

答案 0 :(得分:2)

  

这当然有效,因为{a:'a'}隐含了任何

这是错误的。 { a : 'a' }的类型为{ a: 'a' }

此函数没有错误,因为TypeScript可以看到您正在返回新的对象文字(也称为“新鲜”)。如果它是一个新的对象文字,则它不能具有任何其他属性,因此TypeScript可以静态检查其所有属性是否可分配给索引签名类型。

在下一个示例中,类型断言{ b : 'b' } as B使新鲜度检查失败(类型断言总是删除有关原始表达式的所有类型信息)。由于TypeScript不能判断此表达式是否实际上是该表达式的别名,该表达式可能具有其他属性,因此必须发出错误。

在上一个示例中,您说过([index: string]: any]),需要一个对象,其所有属性在某种程度上都与any兼容。您编写的对象是否是其属性都与any兼容的对象?当然是的;所有类型都具有该属性。这样代码就可以了。