LoginSignup
3
1

More than 3 years have passed since last update.

TypeScript ツメ将棋ならぬツメ型定義🥺

Posted at

こんにちは

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項演算子の返却部分で参照できる。

参考) https://log.pocka.io/posts/typescript-promisetype/

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1