Open13

型関連

haseyuyhaseyuy
// typeof演算子を使った型ガード
function doSomething(x: number | string) {
    if (typeof x === 'string') {
        // xがstring型の場合の処理
        console.log(x.toUpperCase());
    } else {
        // string型でないことが絞り込まれるので、number型になる
        console.log(x.toFixed(2));
    }
}
doSomething('max');//->MAX
doSomething(123);//->123.00
haseyuyhaseyuy
// in演算子を使った型ガード
// オブジェクトにプロパティが存在するかどうかをチェック
function doSomething2(x: Person | Book) {
    if ('age' in x) {
        // xがPerson型の場合の処理
        console.log(x.name);
    } else {
        // xがBook型の場合の処理
        console.log(x.name);
    }
}

doSomething2({ name: 'max', age: 30 }); //-> max
doSomething2({ name: 'typescript', price: 1000 }); //->typescript
haseyuyhaseyuy

ユーザー定義型ガードのエラーが出る例

const isString = (data: unknown): Boolean => {
    return typeof data === 'string';
};

const test = (data: unknown) => {
    if (!isString(data)) {
        console.log(data);
        return;
    }
    // dataはunknown型なので、toUpperCaseが実行できない
    console.log(`OK: ${data.toUpperCase()}`);
};
haseyuyhaseyuy

ユーザー定義型ガードの正しい例

// 関数の戻り値の型をx is TypeとしてNarrowingする
const isString = (data: unknown): data is string => {
    return typeof data === 'string';
};

const test = (data: unknown) => {
    if (!isString(data)) {
        console.log(data);
        return;
    }
    console.log(`OK: ${data.toUpperCase()}`);
};

test('test'); //->TEST
haseyuyhaseyuy

Partial<T>

interface Person {
    firstName: string;
    lastName: string;
    age: number;
}

// Constructs a type with all properties of Type set to optional.
// This utility will return a type that represents all subsets of a given type.
const taro: Partial<Person> = {
    firstName: 'Taro',
}

Required<T>

interface Props {
    a?: number;
    b?: string;
}
// Constructs a type consisting of all properties of Type set to required.
// The opposite of Partial.
// property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.
const obj: Required<Props> = { a: 5 };
haseyuyhaseyuy

Readonly<T>

interface Todo {
    title: string;
}

// Constructs a type with all properties of Type set to readonly,
// meaning the properties of the constructed type cannot be reassigned.
const todo: Readonly<Todo> = {
    title: 'Todo'
};

// Cannot assign to 'title' because it is a read-only property.
todo.title = 'Todo1';
haseyuyhaseyuy

Record<Keys, Type>

interface Catinfo {
    age: number;
    breed: string;
}

type CatName = "miffy" | "boris" | "mordred"

// Constructs an object type whose property keys are Keys and whose property values are Type.
// This utility can be used to map the properties of a type to another type.
const cats: Record<CatName, Catinfo> = {
    miffy: { age: 1, breed: "tabby" },
    boris: { age: 2, breed: "tabby" },
    mordred: { age: 3, breed: "Persian" },
};

//const cats: Record<CatName, Catinfo>
cats
haseyuyhaseyuy

Pick<Type, Keys>

interface Todo {
    title: string;
    description: string;
    completed: boolean;
}

// Constructs a type by picking the set of properties Keys (string
// literal or union of string literals) from Type.
type TodoPreview = Pick<Todo, "title" | "completed">;

const todo: TodoPreview = {
    title: "Learn TypeScript",
    completed: false
}
haseyuyhaseyuy

NonNullable<T>

// Constructs a type by excluding null and undefined from Type.

// type T0 = string | number
type T0 = NonNullable<string | number | undefined>;

// type T1 = string | number 
type T1 = NonNullable<string | number | undefined | null>;
haseyuyhaseyuy

Conditional Types

interface Animal {
    live(): void;
}

interface Dog extends Animal {
    woof(): void;
}

// type Example1 = number
type Example1 = Dog extends Animal ? number : string;

// type Example2 = string
type Example2 = RegExp extends Animal ? Dog : string;
haseyuyhaseyuy
//型T, Uをとって、それらが全てString型かどうかを判定
type IsAllString<T, U> = T extends string
  ? U extends string
    ? true
    : false
  : false

// type A = true
type A = IsAllString<"a", "b">
// type B = false
type B = IsAllString<"a", 2>
haseyuyhaseyuy
//型T, Uをとって、それらが全てString型かどうかを判定
type IsAllString<T, U> = [T, U] extends [string, string] ? true : false;

// type A = true
type A = IsAllString<"a", "b">
// type B = false
type B = IsAllString<"a", 2>
haseyuyhaseyuy

指定した特定の方のみを除去

type Square = {
    kind: "square";
    size: number;
}

type Rectangle = {
    kind: "rectangle";
    width: number;
    height: number;
}

type Triangle = {
    kind: "triangle";
    width: number;
    height: number;
}

// 指定した特定の方のみを除去
// 型Tが第二引数の型Uを満たす場合は、never型、満たさない場合はTとなる
type Diff<T, U> = T extends U ? never : T;

// type FourSides = Square | Rectangle
type FourSides = Diff<Square | Rectangle | Triangle, Triangle>;