2017-04-21 46 views
1

使用Typescript 2.2.2(使用strictNullChecks選項爲true)我對以下內容感到驚訝。這是一個錯誤還是有意的行爲?使用上下文類型而不是從推論輸入函數返回

interface Fn { 
    (value: any): number; 
} 

var example1: Fn = function(value) { 
    if (value === -1) { 
     return undefined; // no error, was expecting error 
    } 
    return value; 
}; 

var example2 = function(value: any): number { 
    if (value === -1) { 
     return undefined; // errors correctly 
    } 
    return value; 
}; 

我明白example1不示數爲函數的返回類型推斷爲any | undefined。然後將any | undefinedFn返回類型的上下文類型進行比較,即number,因此發現它們是兼容的。相反,我希望返回類型的功能由上下文輸入設置,而不是與其相比。有沒有什麼辦法可以強制使用Fn這個消費者也明確地鍵入函數return?

我想這回到接口只提供必須履行合同,而不是指定實現包括返回類型。

而且(出於興趣)的錯誤顯然被抓住時,參數類型(number)引起的推斷返回類型(number | undefined)要與上下文類型不兼容(從Fn2,即number):

interface Fn2 { 
    (value: number): number; 
} 

// `example3` errors as function return type is inferred to be `number | undefined` which is incompatible with the expected `number` return type. 
var example3: Fn2 = function(value) { 
    if (value === -1) { 
     return undefined; 
    } 
    return value; 
}; 

回答

1

一種解決方法是使用所有可用的原語和非原語來代替any

interface Fn { 
    (value: number | string | boolean | null | undefined | object): number; 
} 

// `example1` now errors as expected due to having a return type which is incompatible: 
//  Type 'string | number | boolean | object | null | undefined' is not assignable to type 'number'. 
//   Type 'undefined' is not assignable to type 'number'. 
var example1: Fn = function(value) { 
    if (value === -1) { 
     return undefined; 
    } 
    return value; 
}; 

For an excellent explanation of why this works please see FstTesla's answer.

1

您分配給example1的函數表達式的確切推斷類型爲(value: any) => any,因爲返回類型any | undefined被「摺疊」爲any。這種類型與Fn兼容,因此被接受。

我想這回到接口只提供必須履行合同,而不是指定包括返回類型的實現。

這是不正確的。相反,類型一致性是非常嚴格的–這就是TypeScript的目的,畢竟:) –除當然當涉及any,是語言中最寬容的類型。

上下文類型不會將變量上聲明的類型應用於函數表達式。相反,return語句的類型有助於確定函數表達式的類型。出於這個原因,我認爲沒有明確的類型註釋在example1的表達式中顯示的剪輯中沒有辦法實現類型安全。

請注意,example1example3之間的差額,實際上是規定是any特殊的,包括undefined,導致第一段所述的「崩潰」的行爲。