簡體   English   中英

為什么我不能間接返回一個對象文字來滿足TypeScript中的索引簽名返回類型?

[英]Why can't I indirectly return an object literal to satisfy an index signature return type in TypeScript?

這三個函數似乎做同樣的事情,但最后一個是錯誤。 為什么會這樣?

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?
}

這種行為正在消失。

從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的類型沒有索引簽名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM