extends keyof
オブジェクト(配列)のkey達を取得する
export interface FormValues {
last_name: string | null;
first_name: string | null;
gender: number | null;
birthday: string | null;
}
const event = <K extends keyof FormValues>(
val: FormValues[K] // FormValuesの中のいずれかのプロパティ,
key: K, // last_name | first_name | gender | birthday
) => {
FormValues[key] = val; // オブジェクトの中の1つのプロパティに代入する
}
継承
interfaceやtypeを追加で定義する
interface Object {
name: string;
height: number;
}
interface newObject extends Object {
birthday: string;
}
const data:newObject =
{
name: '澁谷かのん',
height: 159,
birthday: '05/01',
}
合併型(Union Types)と交差型(Intersection Types)
合併型はorを表す型で、交差型は&を表す型
type Kick = {
effect: boolean,
hit: boolean,
};
type Punch = {
hit: boolean,
damage: number,
};
type KickOrPunch = Kick | Punch;
type KickAndPunch = Kick & Punch;
// 合併型なので、Kick, Punch型両方のプロパティが使える
const SuperAtack: KickOrPunch = {
effect: true,
hit: true,
damage: 10,
};
// 合併型なため、どちらかの型ということを表せれば良い
const normalAtack: KickOrPunch = {
hit: false,
damage: 3,
};
// 合併型とはいえどちらかの型を満たせなけれNG
const errorAtack: KickOrPunch = {
effect: false,
damage: 3,
};
// Type '{ effect: false; damage: number; }' is not assignable to type 'KickOrPunch'.
// Property 'hit' is missing in type '{ effect: false; damage: number; }' but required in type 'Punch'.
// 交差型なので、合併型同様Kick, Punch型両方のプロパティが使える
const doubleAtack: KickAndPunch = {
effect: true,
hit: true,
damage: 10,
};
// 交差型は集合元の型全てのプロパティを使わなくてはならない
const errorAtack2: KickAndPunch = {
hit: true,
damage: 3,
};
// Type '{ hit: true; damage: number; }' is not assignable to type 'KickAndPunch'.
// Property 'effect' is missing in type '{ hit: true; damage: number; }' but required in type 'Kick'.
interfaceとtypeの違い
1.interfaceではオブジェクトとクラスの型だけ定義できるが、typeでは他の型も参照できる
2.interfaceは拡張ができるが、typeはできない(スコープ内で重複できない)
interface User {
name: string;
}
interface User {
level: number;
}
const user: User = {
name: "apple",
level: 0
};
------------------------------------------------------
type User = {
name: string;
} //Duplicate identifier 'User'
type User = {
level: number;
} //Duplicate identifier 'User'
3.typeのみ三項演算子が使える
type User<T extends boolean> = T extends true ? number : string
const truthyValue: User<true> = 156;
const falsyValue: User<false> = '愛本輪怐';
4.typeは数も同じでなければならない(タプル)
interface A {
0: number;
1: string;
2: number;
}
type B = [number, string, number];
// ok
const a: A = [0, '1', 2, 3];
const b: B = [0, '1', 2, 3]
// Type '[number, string, number, number]' is not assignable to type 'B'.
// Types of property 'length' are incompatible.
// Type '4' is not assignable to type '3'.
参考
https://zenn.dev/luvmini511/articles/6c6f69481c2d17
https://nju33.com/notes/typescript/articles/Interface と Type の比較#三項演算子https://qiita.com/tkrkt/items/d01b96363e58a7df830e
Mapped Types
指定した型を変換して新しい型を生成する機能
リテラル型とプリミティブ型
プリミティブ型はnumber, string, null, undefined
などのこと。
リテラル型とはプリミティブ型の特定の値だけを許容する型
const impossible: false = false;
const three: 3 = 3;
const radetzky: 'Radetzky' = 'Radetzky';
型アサーション(as)
型定義の上書き機能。型アサーションを使えば、任意のタイミングで型を上書きできちゃうため型安全性が全く保証されないので注意
type Foo = {
bar: number;
bas: string;
}
const foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';
unknownとanyの違い
unknown型に代入したオブジェクトのプロパティ、メソッドは型ガードや型アサーションを経由しないと使用(実行)できない。
const unknown1: unknown = 0.8;
const unknown2: unknown = 'Comment allez-vous';
const unknown3: unknown = {
x: 0,
y: 1,
name: 'origin'
};
console.log(unknown1.toFixed());
// Object is of type 'unknown'.
console.log(unknown2.length);
// Object is of type 'unknown'.
console.log(unknown3.name);
// Object is of type 'unknown'.
anyと違い、型ガードはしっかりされる
function toString(n: unknown): string {
switch (typeof n) {
case 'object':
if (n === null) {
return n.substr(1);
// Object is possibly 'null'.
}
return n.substr(1);
// Property 'substr' does not exist on type 'object'
case 'string':
return n.substr(1);
default:
return n.substr(1);
// Object is of type 'unknown'.
}
}
Partial
すべてのプロパティにOptional(任意)であることを意味する?を適用します。
interface User {
name?: string,
height?: string,
age?: number,
}
function findUsers(
name?: string,
height?: string,
age?: number,
): void {
console.log(age);
}
// OKだけど引数の分だけundefined入れるのはだるい・・・
findUsers(undefined, undefined, 22);
interface User {
name?: string,
height?: string,
age?: number,
}
type FindUsersArgs = Partial<User>;
function findUsers({ name, height, age }: FindUsersArgs):
void {
console.log(age);
}
// 引数1つでOK!
findUsers({ age : 22 });
Required
すべてのプロパティからOptionalであることを意味する?を取り除く
interface User {
name?: string,
height?: string,
age?: number,
}
type FindUsersArgs = Required<User>;
function findUsers({ name, height, age }: FindUsersArgs):
void {
console.log(age);
}
findUsers({ age : 22 });
// Argument of type '{ age: number; }' is not assignable to parameter of type 'Required<User>'.Type '{ age: number; }' is missing the following properties from type 'Required<User>': name, height
Record
以下の書式を持つ組み込み型で、Kに指定したキーに対して、型Tを設定してくれるものです。
// Record<K extends string | number | symbol, T> Kに指定された型をキーにして,それぞれに対して、型Tを設定する。
type User = {
address: string;
name: String;
};
const Users:Record<number , User> = {
1 : {
address: "Shinjuku",
name: "user1"
},
2 : {
address: "Shibuya",
name: "user2"
},
'idol':{
address: "Nakano",
name: "user3"
},
// Type '{ 1: { address: string; name: string; }; 2: { address: string; name: string; }; idol: { address: string; name: string; }; }' is not assignable to type 'Record<number, User>'.Object literal may only specify known properties, and ''idol'' does not exist in type 'Record<number, User>'.
};
Pick
既に存在するT型の中からKで選択した一部のプロパティのみを含んだ新たな型を構築します。
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>
const preview: TodoPreview = {
title: '部屋の掃除',
completed: false,
}
console.log(preview)
Omit
Omitは既に存在するT型の中からKで選択した一部のプロパティを除いた新たな型を構築します。
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Omit<Todo, 'description'>
const preview: TodoPreview = {
title: '部屋の掃除',
completed: false,
}
console.log(preview) //=> { title: '部屋の掃除', completed: false }
// export interface MaintenanceConfirmData
// extends Omit<MaintenanceRequestData, 'old_inputs'> {
// inputs: MaintenanceRequestForm;
// }
Exclude
ユニオン型TからUを取り除きます。
type Grade = 'A' | 'B' | 'C' | 'D' | 'E';
// A~DがOK
type PassGrade = Exclude<Grade, 'E'>;
Extract
Excludeと逆です。ユニオン型TからUを抽出します。
type Grade = 'A' | 'B' | 'C' | 'D' | 'E';
// EのみOK
type FailGrade = Extract<Grade, 'E'>;
タプル
複数の値を保持することのできる型です。 [] 記号を使うところも配列によく似ていますが、それぞれの位置の要素の型を明示しておくことができます。
let vote: [string,number]
vote = ['red', 100];// OK
vote = ['green', 200];// OK
vote = ['yellow', 300];// OK
vote = ['AAA', 'BBB'];// Error
参考: https://maku.blog/p/6uzqf4q/
ユニオン型 (Union Types)
ReturnType
関数の返り値を型に変換する
const foo = ()=> {
return {
foo: 1,
fooo: 2,
foooo: 3
}
}
type Foo = ReturnType<typeof foo>
/* type Foo = {
foo: 1,
fooo: 2,
foooo: 3
}
*/