インターセクション型
A & Bのような型のことを言います。
↓EngineerとBloggerオブジェクトの全てを入れる必要があります。
↓被っているものは1つで良いとみなされるので、nameも1つで大丈夫です。
type Engineer = {
name: string;
role: string;
}
type Blogger = {
name: string;
follower: number;
}
type EngineerBlogger = Engineer & Blogger;
const quill: EngineerBlogger = {
name: 'quill',
role: 'front-end',
follower: 1000
}
↓だったら、type Mixはnumber型になります。
↓NumberBooleanとStringNumberで重複しているのがnumberのみだからです。
type NumberBoolean = number | boolean;
type StringNumber = string | number;
type Mix = NumberBoolean & StringNumber;
Type guard
条件分を使って、型を絞り込んでいく方法です。
typeof
function toUpperCase(x: string | number) {
if (typeof x === 'string') {
return x.toUpperCase();
}
return '';
}
in演算子
↓nomadWorkerというオブジェクトにroleキーは存在しますか?という意味になります。
↓存在すればtrueを返します。
function describeProfile(nomadWorker: NomadWorker) {
console.log(nomadWorker.name);
if ('role' in nomadWorker) {
console.log(nomadWorker.role);
}
}
instanceof
classの場合使えます。
↓if (pet instanceof Bird)は、「petはBirdのインスタンスですか?」と言っています。
↓Birdクラスから設計されたインスタンスだった場合にtrueを返します。
class Dog {
speak() {
console.log('bow-wow');
}
}
class Bird {
speak() {
console.log('tweet-tweet');
}
fly() {
console.log('flutter');
}
}
type Pet = Dog | Bird;
function havepet(pet: Pet) {
pet.speak();
if (pet instanceof Bird) {
pet.fly();
}
}
Tagged union
Type guardのように型を絞り込んでいく、Tagged unionデザインパターンです。
↓DogにもBirdにもkindを置いて、switchに指定して、caseで判別するといった方法です。
class Dog {
kind: 'dog' = 'dog'
speak() {
console.log('bow-wow');
}
}
class Bird {
kind: 'bird' = 'bird'
speak() {
console.log('tweet-tweet');
}
fly() {
console.log('flutter');
}
}
type Pet = Dog | Bird;
function havepet(pet: Pet) {
pet.speak();
switch(pet.kind) {
case 'bird': pet.fly();
}
Type assertion
手動で型を上書きする方法です。
↓2つとも意味は同じです。
↓document.getElementById('input')を、手動で無理やり「HTMLInputElementです!」と
↓Typescriptに教えてあげています。
↓そうしないとinputがHTMLInputElementかnullかが分からないからです。
const input = <HTMLInputElement>document.getElementById('input');
const input = document.getElementById('input') as HTMLInputElement;
Non-null assertion operator
↓末尾についている ! は、絶対にnullじゃないと言い切るものです。
const input = document.getElementById('input')!;
Index signature
オブジェクトの中身を追加できるというものです。
↓通常オブジェクトに中身を追加できなくて、エラーが起きます。

↓[index: string]: string;という一文を付け加えると、全てOKになります。
↓ただし、[index: string]: string;の最後の型がstringだったら、
↓他のメンバーも全てstring型にしないといけません。(例えばageなど)

↓[index: number]: string;とすると、キーが数値でないとダメになります。

関数のオーバーロード
関数の戻り値を、正しくTypescriptに伝える方法です。
↓最後の行のupperHelloは、明らかにstringのはずなのにstring | numberと認識されています。
↓Typescriptには分からないのです。
function toUpperCase(x: string | number):string | number {
if (typeof x === 'string') {
return x.toUpperCase();
}
return x;
}
const upperHello = toUpperCase('Hello');
↓ここで関数のオーバーロードを使います。
↓function toUpperCase(x: string): string; = stringの返り値はstringだよー
↓function toUpperCase(x: number): number; = numberの返り値はnumberだよー
↓としてあげることで解決します。
function toUpperCase(x: string): string;
function toUpperCase(x: number): number;
function toUpperCase(x: string | number):string | number {
if (typeof x === 'string') {
return x.toUpperCase();
}
return x;
}
const upperHello = toUpperCase('Hello');
これがオーバーロードです。
Optional Chaining
Javascriptは、要はundefinedかnullの
メソッドやプロパティに対してアクセスしようとするとエラーが出ます。
そのエラーを防ぐために何かあったらundefinedで止めておくといった書き方です。
interface DownloadedData {
id: number;
user?: {
name?: {
first: string;
last: string;
}
};
}
const downloadedData: DownloadedData = {
id: 1
}
console.log(downloadedData.user?.name?.first);
↑downloadedData.user?.nameは、
↑downloadedData.userがundefinedもしくはnullだったら、undefinedを返す、
↑それ以外が入っていたら、nameを返すという意味です。
Nullish Coalescing
↓undefinedとnullの2つだけに対しては'no-user'になるといったようなものを
↓Nullish Coalescingと言います。
const userData = downloadedData.user ?? 'no-user';
LookUp型
オブジェクトの型の、メンバーが持っている型にアクセスするときに使います。
↓[ ]で指定すると、そのメンバーの型にアクセスできます。
↓type idはnumber型になっています。
interface DownloadedData {
id: number;
user?: {
name?: {
first: string;
last: string;
}
};
}
type id = DownloadedData['id'];
↓type idは(number | user?)型になっています。
interface DownloadedData {
id: number;
user?: {
name?: {
first: string;
last: string;
}
};
}
type id = DownloadedData['id' | 'user'];
Typescriptの加算演算表
「Typescriptの型安全性」と「Javascriptの柔軟性」
|Any |Boolean |Number |String |Other
--------|---------|-------|------|--------|------------
Any | Any | Any | Any | String | Any
Boolean | Any | | | String |
Number | Any | |Number| String |
String | String | String|String| String |String
Other | Any | | | String |
オーバーロードを型で表現する
↓オーバーロードを型で表現する場合は、
↓オーバーロードした全ての関数に対応した関数しか入れれません。
interface TmpFunc {
(x: string): number;
(x: number): number;
}
const upperHello: TmpFunc = function(x: string | number) { return 0 };
//string と numberに対応した型の関数しか使えない
関数型のIntersection
interface FuncA {
(a: number, b: string): number;
(a: string, b: number): number;
}
interface FuncB {
(a: string): number;
}
let intersectionFunc: FuncA & FuncB;
↑intersectionFunc: FuncA & FuncB;は、
↓のようにオーバーロードされた型になっています。
(a: number, b: string): number;
(a: string, b: number): number;
(a: string): number;
関数型のUnion型
↓unionFuncは、パラメーターはintersection型になり、戻り値はunion型になります。
interface FuncA {
(a: number): number;
}
interface FuncB {
(a: string): string;
}
let unionFunc: FuncA | FuncB;
Rest Parameter
↓関数advanceFnに、いくつも引数を入れられるよーというものです。
↓.を3つ付けてその後名前を付けます。
↓するとその名前が配列としてadvanceFn使えます。
↓さらに: number[ ]のように、配列の型を付けることでRest Parameterに型付けできます。
function advanceFn(...args: number[]) {
args[0];
}
advanceFn(0, 1, 2, 3)
↓Tuple型もつけられます。
↓Optional parameterも付けれます。
↓可変調ではなくなります。
function advanceFn(...args: [number, string, boolean?]) {
}
advanceFn(0, 'web', true);
↓Tuple型に可変長を付けることもできます。
↓... + 型 + 配列
function advanceFn(...args: [number, string, boolean, ...number[]]) {
args[0];
}
advanceFn(0, 'web', true, 0, 1, 2, 3);
配列とTupleにreadonly修飾子を付ける
↓:と配列の間、型のところにreadonlyを付けることができます。
function advanceFn(...args: readonly [number, string, boolean, ...number[]]) {
}
advanceFn(0, 'web', true, 0, 1, 2, 3);
読み物になるので、args.pushで入れれなくなったりします。
const Assertion
as constと付けると、定数のようになります。
↓milkはstring型です。
let milk = 'milk';
↓milkはmilkというString literal型になります。
let milk = 'milk' as const;
↓arrayはnumber[ ]になります。
const array = [10, 20];
↓readonly [10, 20]という、 readonly + Tuple型になります。
const array = [10, 20] as const;
↓はconst peter: {
name: string;
age: number;
}
↓となります。
const peter = {
name: 'peter',
age: 38
}
↓はconst peter: {
readonly name: "peter";
readonly age: 38;
}
↓となります。
const peter = {
name: 'peter',
age: 38
} as const;
型の中でtypeofを使う
↓peterの型を代入したいとき、これではダメです。
↓peterは値なので、PeterTypeは成り立ちません。
const peter = {
name: 'peter',
age: 38
} as const;
type PeterType = peter;
↓そんなときpeterの型を取得するにはtypeofをくっ付けます。
const peter = {
name: 'peter',
age: 38
} as const;
type PeterType = typeof peter;