interface
interfaceは基本オブジェクトにしか使わない。けど関数の型も作ることができる。
// オブジェクトのみで利用可能
interface Person {
name: string;
say(msg:string):void;
}
// エラー
interface func = (num:number) => void;
// エラーにならず関数の型として使える
// この書き方をコールシグネチャという
interface func {
(num:number):void;
}
// けど、関数の型定義はタイプエイリアスの方が分かりやすいので、こっちを使う
type func = (num: number) => void;
継承
// これはどちらも同じ意味
interface A extends B {
name: string;
}
type A = {
name: string;
} & B
同名だけど型が違う場合の継承
//interface
interface Nameable {
name: string;
}
// エラー:型 'number' を型 'string' に割り当てることはできません
interface Human extends Nameable {
name:number;
age: number;
greeting(msg: string): void;
}
// type
type Nameable = {
name: string;
};
// 継承できるが、name:neverとなる
type Human = {
name: number;
age: number;
greeting(message: string): void;
} & Nameable;
コンストラクトシグネチャ
// うーん。使いどころがわからない
interface func {
new (num:number):void;
}
// コンストラクタ専用の型になる
const temp=(cb:func) => {
const foo = new cb(1);
}
関数型(コールシグネチャ)のインターセクション
// 関数型インターフェースA
interface FuncA {
(a: number, b: string): number;
(a: string, b: number): number;
}
// 関数型インターフェースB
interface FuncB {
(a: number): number;
}
// funcFooの型は↓と同じ(FuncAとFuncBをすべてオーバーロードされている)
// interface xxxx {
// (a: number, b: string): number;
// (a: string, b: number): number;
// (a: number): number;
// }
let funcFoo: FuncA & FuncB;
//funcFooに入れられる関数はFuncAとFuncBで定義している型がすべて入るシグネチャにしなければならない
funcFoo = (a:number|string, b?:string|number) => 0;
keyof
トップレベルのプロパティ名のみユニオン型として返す
// type K = "name" | "age"
type K = keyof { name: { first: string; second: string }; age: number };
Mapped Types
型のfor文
基本
type fruit = {
[P in "apple" | "banana"]: P;
};
// type fruit = {
// apple: "apple";
// banana: "banana";
// }
keyofを使う
interface Fruit {
apple: string;
banana: string;
}
type MappedTypes = {
[P in keyof Fruit]: P;
};
// 元のプロパティの型を使いたい場合はT[P]
type MappedTypes<T> = {
[P in keyof T]: T[P];
};
エラー:MappedTypesではプロパティやメソッドを追加できない
interface Fruit {
apple: string;
banana: string;
}
type MappedFruit = {
[P in keyof Fruit]: Fruit[P];
name:string; // マップされた型ではプロパティやメソッドを宣言できません
};
ジェネリクスを使って汎用的にする
// Fruiteインターフェースを読み取り専用にする
interface Fruit {
apple: string;
banana: number;
}
type MappedTypes<T> = {
readonly [P in keyof T]: T[P];
};
type ReadonlyFruit = MappedTypes<Fruit>;
// type ReadonlyFruit = {
// readonly apple: string;
// readonly banana: number;
// }
いろいろカスタム
オプショナルにする
type MappedTypes = {
[P in "apple" | "banana"]?: string;
};
元のプロパティのreadonlyを消す
interface Fruit {
readonly apple: string;
banana: number;
}
type MappedTypes<T> = {
-readonly [P in keyof T]: T[P];
};
type customFruit = MappedTypes<Fruit>;