前言
在面向?qū)ο笳Z言中,接口是一個很重要的概念,它是對行為的抽象,而具體如何行動需要由類去實現(xiàn)。
TypeScript 中的接口是一個非常靈活的概念,除了可用于 對類的一部分行為進行抽象 以外,也常用于對「對象的形狀(Shape)」進行描述。
?TypeScript 的核心原則之一是對值所具有的結構進行類型檢查,并且只要兩個對象的結構一致,屬性和方法的類型一致,則它們的類型就是一致的。? 在TypeScript里,接口的作用就是為這些類型命名和為代碼或第三方代碼定義契約。
簡單點說,在 TypeScript中,接口是一個很重要的特性,它讓 TypeScript 具備了 JavaScript 所缺少的、描述較為復雜數(shù)據(jù)結構的能力。
引入主題
其實在 JavaScript 日常開發(fā)中,很多時候都需要接口來 “規(guī)范” 程序。
假設在 JavaScript 中定義一個函數(shù),用來獲取一個用戶的姓名和年齡的字符串:
function getUserInfo(user) {
return `name: ${user.name}, age: ${user.age}`
}
函數(shù)調(diào)用:
getUserInfo({name: "koala", age: 18})
您可能會問,我們寫 JavaScript 的時候,這個再正常不過了吧?
但請注意,如果這個 getUserInfo()
在多人開發(fā)過程中,如果它是個公共函數(shù)(多個開發(fā)者都會調(diào)用),如果不是每個人點進來看函數(shù)對應注釋,可能會出現(xiàn)以下錯誤的調(diào)用:
// 1: 直接調(diào)用,不知道還需要傳參數(shù)
getUserInfo() // Uncaught TypeError: Cannot read property 'name' of undefined
// 2: 只傳遞一個參數(shù),不知道還有其他參數(shù)
console.log(getUserInfo({name: "王佳斌"})) // name: 王佳斌, age: undefined
// 3: 參數(shù)知道傳遞多少個,但不知鍵名
getUserInfo({name: "王佳斌", width: 560}) // name: 王佳斌, age: undefined
// ...
由于 JavaScript 是弱類型的語言,所以 并不會對我們傳入的代碼進行任何的檢測,
?? 有些錯你自己都說不清楚,但是就出了問題。
那么如何解決呢?有請 Typescript 接口登場。
創(chuàng)建接口
指定的接口名稱,最好與普通變量名 “有所區(qū)分” ,比如接口名首字母大寫、首字母前綴(In_xxx)等。
在 Typescript 中,使用 interface
關鍵字來定義一個接口,其中 name
就是接口名稱。
interface name {}
基礎使用
Typescript 接口可以規(guī)定函數(shù)的 “形狀”,也可以規(guī)定變量的 “形狀”,下面有兩個示例。
以下 JavaScript 例子(前面已經(jīng)提到了,忘記的話往前翻):
function getUserInfo(user) {
return `name: ${user.name}, age: ${user.age}`
}
這個所存在的問題大家已經(jīng)知道了,下面用 Typescript 接口進行函數(shù)重構。
// 規(guī)定"形狀"
interface Info {
name: string;
age: number;
}
// 函數(shù)(冒號后跟上 "接口名")
function getUserInfo({ name, age }: Info) {
return `name: ${name}, age: ${age}`
}
// 正常都傳遞
console.log(getUserInfo({ name: '王佳斌', age: 123 }))
// 結果OK:"name: 王佳斌, age: 123"
// 少傳遞一個
console.log(getUserInfo({ name: '王佳斌' }))
// Property 'age' is missing in type '{ name: string; }' but required in type 'Info'.
// 類型“{name:string;}”中缺少屬性“age”,但類型“Info”中需要該屬性。
// 都不傳遞
console.log(getUserInfo())
// Expected 1 arguments, but got 0.
// 應為1個參數(shù),但得到了0個。
你看,這些都是在編寫代碼時 TypeScript 提示的錯誤信息,這樣就避免了在使用函數(shù)的時候傳入不正確的參數(shù)。
注意:在定義接口時,不要把它理解為是在定義一個對象,{}
括號包裹的是一個代碼塊,里面是聲明語句,只不過聲明的不是變量的值而是類型。聲明也不用等號賦值,而是冒號指定類型。每條聲明之前用換行分隔即可,也可以使用分號或者逗號。
另外,接口還可以被變量所使用(繼承接口的 “形狀”),如下代碼所示:
// 規(guī)定"形狀"
interface Info {
name: string;
age: number;
}
// 變量 "繼承" 接口
const student: Info = {
name: '小王',
age: 15
}
// 測試變量
console.log(student)//{"name": "小王", "age": 15}
// 錯誤用法(比如寫一個 "Info" 接口不存在的參數(shù))
const err: Info = {
a: 1
}
// Object literal may only specify known properties, and 'a' does not exist in type 'Info'.
// 對象文字只能指定已知的財產(chǎn),類型“Info”中不存在“a”。
可選屬性
當然,TypeScript 中也允許不 “必傳” 某些參數(shù),有這個字段就做處理,沒有就忽略。
如下代碼所示,message
參數(shù)可以不傳遞。
// 使用 "?" 表示此參數(shù)非必傳
interface Log {
message?: string;
}
// 函數(shù)
function print({ message }: Log) {
console.log(message || '該參數(shù)沒有傳遞~')
}
// 傳遞參數(shù)
print({ message: 'hello' }) //"hello"
// 不傳遞
print({}) //"該參數(shù)沒有傳遞~"
很好理解。
只讀屬性
TypeScript 支持將某些參數(shù)設置為 “只讀”,用于限制只能在對象剛剛創(chuàng)建的時候修改其值,后續(xù)無法再修改。
如下代碼所示,age
參數(shù)不可后期修改。
// 使用 "readonly" 關鍵字表示此參數(shù)"只讀"
interface Info {
name: string;
readonly age: number;
}
// 創(chuàng)建變量("age"只能初始的時候賦值一次)
const student: Info = {
name: '小王',
age: 15
}
// 測試修改只讀屬性 "age"
student.age = 50
// Cannot assign to 'age' because it is a read-only property.
// 無法分配給“age”,因為它是只讀屬性。
此外 TypeScript 還提供了 ReadonlyArray<T>
類型,它與 Array<T>
相似,只是把所有可變方法去掉了,因此可以確保數(shù)組創(chuàng)建后再也不能被修改。
// 創(chuàng)建一個 "絕對不可修改" 的數(shù)組(number類型)
let arr: ReadonlyArray<number> = [1, 2, 3, 4]
// 測試賦值
arr[0] = 10
// Index signature in type 'readonly number[]' only permits reading.
// 類型為“只讀數(shù)字[]”的索引簽名只允許讀取。
// 測試添加數(shù)組項
arr.push(5)
// Property 'push' does not exist on type 'readonly number[]'.
// 類型“只讀數(shù)字[]”上不存在屬性“push”。
// 測試賦值數(shù)組長度
arr.length = 99
// Cannot assign to 'length' because it is a read-only property.
// 無法分配給“l(fā)ength”,因為它是只讀屬性。
任意屬性
有時候我們希望一個接口中除了包含必選和可選屬性之外,還允許有其他的任意屬性,這時我們可以使用 索引簽名 的形式來滿足上述要求。
如下代碼所示,除了 name
必傳外,后面你可以隨意傳遞參數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-413893.html
// 使用 "[propName: string]: any" 支持任意類型
interface Person {
name: string;
[propName: string]: any;
}
// 只傳遞必填,其他參數(shù)不要
const a: Person = { name: '小王' }
console.log(a) //{"name": "小王"}
// 傳遞必填,其他參數(shù)隨意傳遞
const b: Person = { name: '小王', age: 15, sex: '男' }
console.log(b) //{"name": "小王", "age": 15, "sex": "男"}
很好理解。文章來源地址http://www.zghlxwxcb.cn/news/detail-413893.html
到了這里,關于Typescript - 通俗易懂的 interface 接口,創(chuàng)建接口 / 基礎使用 / 可選屬性 / 只讀屬性 / 任意屬性(詳細教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!