为什么我不能间接返回一个对象文字来满足TypeScript中的索引签名返回类型?

 mobiledu2502889283 发布于 2023-01-20 20:49

这三个函数似乎做同样的事情,但最后一个是错误.为什么会这样?

interface StringMap {
    [key: string]: string;
}

function a(): StringMap {
    return { a: "1" }; // OK
}

function b(): StringMap {
    var result: StringMap = { a: "1" };
    return result; // OK
}

function c(): StringMap {
    var result = { a: "1" };
    return result; // Error - result lacks index signature, why?
}

Ryan Cavanau.. 30

这种行为正在消失.

从TypeScript 1.8之后的任何版本开始(或者现在,如果你使用的是最前沿的编译器),当一个类型的原始表达式是一个对象文字时,你将不会再看到这个错误.

请参阅https://github.com/Microsoft/TypeScript/pull/7029


旧编译器的旧答案

索引签名和对象文字在TypeScript中特别表现.从规范4.5节,对象文字:

当对象文字由包含类型T的字符串索引签名的类型进行上下文类型化时,对象文字的结果类型包括字符串索引签名,其中扩展形式为最常见的T类型和声明的属性类型在对象文字中.

这是什么意思呢?

上下文打字

当表达式的上下文提示其类型可能是什么时,就会发生上下文类型.例如,在此初始化中:

var x: number = y;

表达式y获取上下文类型,number因为它正在初始化该类型的值.在这种情况下,没有什么特别的事情发生,但在其他情况下会发生更有趣的事情.

最有用的案例之一是功能:

// Error: string does not contain a function called 'ToUpper'
var x: (n: string) => void = (s) => console.log(s.ToUpper());

编译器s是如何知道这是一个字符串?如果您自己编写该函数表达式,则为s类型,any并且不会发出任何错误.但是因为函数是由类型的上下文键入x,所以参数s获取了类型string.很有用!

索引签名

一个索引签名指定当一个对象被一个字符串或数字索引的类型.当然,这些签名是类型检查的一部分:

var x: { [n: string]: Car; };
var y: { [n: string]: Animal; };
x = y; // Error: Cars are not Animals, this is invalid

缺少索引签名也很重要:

var x: { [n: string]: Car; };
var y: { name: Car; };
x = y; // Error: y doesn't have an index signature that returns a Car

希望上述两个片段显然应该导致错误.这导致我们......

索引签名和上下文键入

假设对象没有索引签名的问题是您无法初始化具有索引签名的对象:

var c: Car;
// Error, or not?
var x: { [n: string]: Car } = { 'mine': c };

解决方案是,当对象文字由具有索引签名的类型进行上下文类型化时,如果匹配,则将该索引签名添加到对象文本的类型.例如:

var c: Car;
var a: Animal;
// OK
var x: { [n: string]: Car } = { 'mine': c };
// Not OK: Animal is not Car
var y: { [n: string]: Car } = { 'mine': a };

把它放在一起

让我们看一下问题中的原始函数:

function a(): StringMap {
    return { a: "1" }; // OK
}

好的,因为return语句中的表达式是由函数的返回类型在上下文中键入的.对象文字{a: "1"}具有其唯一属性的字符串值,因此可以成功应用索引签名.

function b(): StringMap {
    var result: StringMap = { a: "1" };
    return result; // OK
}

好的,因为显式类型变量的初始化器是由变量类型的上下文类型.和以前一样,索引签名被添加到对象文字的类型中.

function c(): StringMap {
    var result = { a: "1" };
    return result; // Error - result lacks index signature, why?
}

不行,因为result的类型没有索引签名.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有