フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

TypeScriptのAdvanced Type①

はじめに

  • 久しぶりにTypescriptの勉強を再開する
  • タイプをモデル化するためのより高度な方法をいくつか調べてみた。

前回の記事

  • 下記の記事の続編

px-wing.hatenablog.com

px-wing.hatenablog.com

px-wing.hatenablog.com

Advanced Types

https://www.typescriptlang.org/docs/handbook/advanced-types.html

Intersection Types(交差型)

  • 複数のタイプを1つに組み合わせます。これにより、既存のタイプを追加して、必要なすべての機能を備えた単一のタイプを取得できます。 たとえば、Person&Serializable&Loggableは、PersonおよびSerializable and Loggableです。 つまり、このタイプのオブジェクトには、3つのタイプすべてのすべてのメンバーが含まれます。

  • AかつB(union型はAまたはB)

  • & で指定したすべての型に含まれるものすべてを定義する必要がある。かぶっているものは1つだけ定義する
type Enginner ={
    name: string;
    role: string;
}

type Twitter = {
    name: string,
    follower: number
}

type EnginnerTwitter = Enginner & Twitter

const person: EnginnerTwitter ={
    name: 'Yamda',
    role: 'reader',
    follower: 200
}
  • interface型の場合
interface Enginner {
    name: string;
    role: string;
}

interface Twitter {
    name: string,
    follower: number
}

interface EnginnerTwitter extends Enginner, Twitter = {}

const person: EnginnerTwitter ={
    name: 'Yamda',
    role: 'reader',
    follower: 200
}
  • 下記のように記述することが可能。
type test1 = number | boolean
type test2 = string | number
type test = test1 & test2

## 数値は入れられるが、文字列は入れれない。
const abc: test = 0

Type Guards

  • 条件文を使って型を絞り込んでいく方法。 www.typescriptlang.org

  • 3つの演算子を使って実現することが可能。 1) .typeof演算子

  • typeofの戻り値は「bigint」「boolean」「function」「number」「object」「string」「symbol」「undefined」
function toUpperCase(x: string | number){
    if (typeof x === 'string'){
        return x.toUpperCase();
    }else if(typeof x === 'number'){
        return String(x)
    }
}

2) .in演算子

type FreeLance = Enginner | Twitter
function profileInfo(freeLance: FreeLance) {
    console.log(freeLance.name)
    // オブジェクトにroleプロパティがあるかチェックし、含まれていたらログ出力
    if ('role' in freeLance) {
        console.log(freeLance.role);
    }
    // オブジェクトにfollowerプロパティがあるかチェックし、含まれていたらログ出力
    if ('follower' in freeLance) {
        console.log(freeLance.follower);
    }
}

3) . instanseof演算子

class Foo {
    foo = 123;
}

class Bar {
    bar = 123;
}

function doStuff(arg: Foo | Bar) {
    if (arg instanceof Foo) {
        console.log(arg.foo); // OK
        console.log(arg.bar); // Error!
    }
    else {  // MUST BE Bar!
        console.log(arg.foo); // Error!
        console.log(arg.bar); // OK
    }
}

doStuff(new Foo());
doStuff(new Bar());

タグ付きunion / 判別共用体(Discriminated Unions)

  • シングルトンタイプ、ユニオンタイプ、タイプガード、タイプエイリアスを組み合わせて、タグ付きユニオンまたは代数的データタイプとも呼ばれる、判別ユニオンと呼ばれる高度なパターンを構築できます。
interface Square {
    kind: "square";
    size: number;
}
interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}
interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape) {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.height * s.width;
        case "circle": return Math.PI * s.radius ** 2;
    }
}