こんにちは
TypeScriptの型定義の文法を調べてるとき、こんな記法あったのか~と唸ったことが何回かあったので、型定義クイズを作ってみました。
全4問あります。
コード中の ???
に何を入力すべきか当ててみてください。
※TypeScriptのバージョンは3.8です。
問題
問1 難易度★★☆☆☆
Dict
インタフェースが、dict
, dict2
共に型一致するよう???を埋めてください。
interface Dict {
???: number | string;
}
const dict: Dict = {
a: 100,
b: 200
};
const dict2: Dict = {
hello: 'world'
};
問2 難易度★★★☆☆
shopList
の型はBook
インタフェースのshop
プロパティと同じ型です。
???を埋めて、shopList
に正しい型を指定してください。
interface Book {
author: string;
price: number;
shop: {
name: string;
sales: number;
}[];
}
const shopList: Book??? = [{
name: 'BookOn',
sales: 123
}, {
name: 'Yafoo',
sales: 100
}];
問3 難易度★★★★☆
UserValidFunc2の???を埋めて、UserValidFuncと同じ型にして下さい
interface User {
name: string;
age: number;
tag: string[];
}
type UserValidFunc = {
name: (p: string) => boolean;
age: (p: number) => boolean;
tag: (p: string[]) => boolean;
}
type UserValidFunc2 = {
[???]: (p: ???) => boolean;
}
問4 難易度★★★★★
UnArrayは指定された型Tの配列でない型を返す型
例) UnArray === string
type UnArray<T> = ???;
const n: UnArray<number[]> = 1;
const s: UnArray<string[]> = 'str';
const b: UnArray<boolean[]> = false;
正解
問1
interface Dict {
[key: string]: number | string;
}
インデックスシグネチャを使う
参考) https://typescript-jp.gitbook.io/deep-dive/type-system/index-signatures#indekkusushigunechawosuru
- インタフェースのプロパティを定義する際は、通常
プロパティ名: 型名;
と定義します、が[key: キーの型名]: 型名;
と定義することで、任意のプロパティに対する型指定を行えます。
問2
const shopOnly: Book['shop'] = [{
name: 'BookOn',
Lookup Typesを使う
参考) https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types
-
型名['プロパティ名']
でプロパティの型を取得できる。
問3
type UserValidFunc2 = {
[P in keyof User]: (p: User[P]) => boolean;
}
Mapped Typesを使う
参考) https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types
Mapped Types の展開の説明
[P in keyof User]: (p: User[P]) => boolean;
↓ 1) 'keyofが展開される' keyof User -> ('name' | 'age' | 'tag')
[P in ('name' | 'age' | 'tag')]: (p: User[P]) => boolean;
↓ 2) 'in で各プロパティ名がPに展開される'
['name']: (p: User['name']) => boolean;
['age']: (p: User['age']) => boolean;
['tag']: (p: User['tag']) => boolean;
↓ 3) '整理する'
name: (p: string) => boolean;
age: (p: number) => boolean;
tag: (p: string[]) => boolean;
問4
type UnArray<T> = T extends (infer R)[] ? R : never;
- type定義の右辺で
extends
を記載すると、型を継承しているかで3項演算子的な条件分岐を行うことができる。 - 条件式で
infer Hogehoge
を記載すると型推論が働いたうえ、3項演算子の返却部分で参照できる。