One of TypeScript's core principles is that type-checking focuses on the 'shape' that values have. This is sometimes called "duck typing" or "structural subtyping". In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project. typescript
實在水平有限,不知道怎麼翻譯。ide
大概的意思應該是,typescript對類型檢查是對"形狀"來判斷的。用函數舉個例子說,就是隻要參數列表被調用的函數所包含,就算是匹配了。函數
你在項目內外編寫的代碼只要符合接口定義的協議,就都能識別。ui
咱們的第一個接口this
咱們經過一個簡單的例子來看接口是如何工做的:編碼
function printLabel(labelledObj: {label: string}) { console.log(labelledObj.label); } var myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj);
The type-checker checks the call to 'printLabel'. The 'printLabel' function has a single parameter that requires that the object passed in has a property called 'label' of type string. Notice that our object actually has more properties than this, but the compiler only checks to that at least the ones required are present and match the types required. spa
調用'printLabel'時,類型檢查器進行檢查。'printLabel'函數須要傳遞一個參數,這個參數是一個對象(labelledObj),而且有一個字符串的屬性——"label"。翻譯
注意,咱們的這個對象實際上可能不止這一個屬性,可是編譯器只會檢查當前這個對象至少符合接口要求的類型,即包含一個label的字符串類型的屬性。code
咱們再以同一個例子,此次使用一個接口來描述須要一個字符串類型的label屬性:對象
interface LabelledValue { label: string; } function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label); } var myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj);
The interface 'LabelledValue' is a name we can now use to describe the requirement in the previous example. It still represents having a single property called 'label' that is of type string. Notice we didn't have to explicitly say that the object we pass to 'printLabel' implements this interface like we might have to in other languages. Here, it's only the shape that matters. If the object we pass to the function meets the requirements listed, then it's allowed.
'LabelledValue'是接口的名字,這個接口用來描述前面那個例子的要求。它表示的仍然是一個叫作label的字符串類型的屬性。
注意,咱們沒有像其餘語言那樣,明確說這個對象實現了LabelledValue接口。在這裏,重要的只是「形狀」(shape)。
若是這個對象符合函數的要求,那麼就是容許的。
It's worth pointing out that the type-checker does not require that these properties come in any sort of order, only that the properties the interface requires are present and have the required type.
值得指出的是:類型檢查並不要求屬性的順序,只要這個屬性符合接口的要求,而且類型匹配,那麼就是容許的。
可選屬性(Optional Properties)
Not all properties of an interface may be required. Some exist under certain conditions or may not be there at all. These optional properties are popular when creating patterns like "option bags" where the user passes an object to a function that only has a couple properties filled in.
並非全部的屬性都是接口要求的。某些存在的條件不是必須的。當用戶傳遞一個對象到一個只有具備一父類擁有的屬性的函數時,這些可選屬性很受歡迎。
下面是這個模式的例子:
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig): {color: string; area: number} { var newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } var mySquare = createSquare({color: "black"});
Interfaces with optional properties are written similar to other interfaces, which each optional property denoted with a '?' as part of the property declaration.
有可選屬性的接口在編碼上與其餘接口相似,每一個可選屬性在屬性聲明時用一個 '?'來表示。
The advantage of optional properties is that you can describe these possibly available properties while still also catching properties that you know are not expected to be available. For example, had we mistyped the name of the property we passed to 'createSquare', we would get an error message letting us know:
可選屬性的優勢是,您能夠描述這些可能可用的屬性,同時還能夠檢查您知道不須要使用的屬性。例如假定傳遞給'createSquare'的屬性名稱拼寫錯誤,則會獲得下面錯誤消息:
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig): {color: string; area: number} { var newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.collor; // Type-checker can catch the mistyped name here } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } var mySquare = createSquare({color: "black"});