[英]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.