[TS] Interfaces
Interfaces @ TypeScript
定義 Interface
Interface 可以用來定義物件,還有由物件所延伸的型別(例如,陣列、函式)
Object
interface Person {
name: string;
age: number;
}
Object / Array
元素都是字串的陣列:
interface StringArray {
[index: number]: string;
}
任何屬性值都可以接收的物件:
interface Dictionary {
[propName: string]: any;
}
Object with methods 物件中的函式/方法
interface Bird {
fly(): void;
}
Function:單純定義函式的 Interface
- 使用在 arrow function 或 function expression
interface GreetFunc {
(name: string, age: number): void;
}
// 如果用 type alias 來定義型別會長這樣
type GreetFunc2 = (name: string, age: number) => void;
// 可以不用額外指定參數型別(參數名稱可以不同)
let greet: GreetFunc = (n, a) => {
console.log(`Hello ${n}, you are ${a} years old`);
};
// 這個 greet function 會自動符合 Greet 這個 interface
let greet: GreetFunc = (name: string, age: number) => {
console.log(`Hello ${name}, you are ${age} years old`);
};
// 即使參數名稱不符合,只要型別符合即會算在這個 Interface
// 例如這裡改用 n, a 當作參數名稱,一樣符合 Greet Interface
let greet: GreetFunc = (n: string, a: number) => {
console.log(`Hello ${n}, you are ${a} years old`);
};
函式參數也可以使用物件的解構賦值:
interface GreetFunc {
(person: { name: string; age: number }): void;
}
const greet: GreetFunc = ({ name, age }) => {
console.log(`Hello ${name}, you are ${age} years old.`);
};
// 或者等同於
const greet = ({ name, age }: { name: string; age: number }) => {
console.log(`Hello ${name}, you are ${age} years old.`);
};
greet({
name: 'Aaron',
age: 32,
});
另外,當一個函式最終不一定有回傳值時,預設會是回傳 undefined,例如:
interface Foo {
(a: number): number;
}
// 由於 foo 這個函式最終可能沒有回傳值
// ❌ 修改 interface:因此在宣告 Foo 時,回傳值要是 `number | undefined`
const foo: Foo = (a) => {
if (a > 5) {
return 3;
}
};
// ⭕️ 修改函式:或者在函式最後拋出錯誤(never),這時候因為 `number | never` 等同於 `number`
// 因此將符合 interface 的定義
const bar: Foo = (a) => {
if (a > 5) {
return 3;
}
throw new Error('a is not over 5');
};
Hybrid:一個物件同時可以當作物件也可以當作函式
interface Shape {
color: string;
}
interface Square extends Shape {
(width: number): string;
width: number;
area(): void;
}
const getSquare = (): Square => {
let square = function (width: number) {
square.width = width;
} as Square;
square.area = () => {
console.log(`the square area is ${square.width * square.width}`);
};
return square;
};
// s 同時是物件,也是函式
const s = getSquare();
s(10);
s.area();
console.log(s.width);