技術ブログ

(技術系中心)基本自分用備忘録なので、あくまで参考程度でお願いします。

Typescriptの応用

// ------------- インターセクション -------------
// エンジニアの型を定義
interface Engineer {
  name: string;
  role: string;
}
// ブロガーの型を定義
interface Blogger {
  name: string;
  follower: number;
}
// type EngineerBlogger = Engineer & Blogger;
// extendsでinterfaceを継承する事ができる
interface EngineerBlogger extends Engineer, Blogger { }

const quill: EngineerBlogger = {
  name: 'Quill',
  role: 'front-end',
  follower: 1000
}

// 型を複数条件定義することも可能
type NumberBoolean = number | boolean;
type StringNumber = string | number;
type Mix = NumberBoolean & StringNumber;

// ------------- type guard -------------
// 関数のオーバーロード(引数がsringの場合はstringを返却する)
function toUpperCase(x: string): string;
// 関数のオーバーロード(引数がnumberの場合はnumberを返却する)
function toUpperCase(x: number): number;

// 型によって、処理を分ける場合はこのように書く(type ofを利用する)
function toUpperCase(x: string | number): string | number {
  if (typeof x === 'string') {
    return x.toUpperCase();
  }
  return x;
}

// ------------- オーバーロードを型で表現する -------------
interface TmpFunc {
  (x: string): number;
  (x: number): number;
}
//string と numberに対応した型の関数しか使えない
const upperHello: TmpFunc = function (x: string | number) { return 0 };

// ------------- 関数型のIntersection -------------
interface FuncA {
  (a: number, b: string): number;
}
interface FuncB {
  (a: string): string;
}

// (a: number, b: string): number;
// (a: string, b: number): number;
// (a: string): number;
let unionFunc: FuncA | FuncB;

// ------------- type guard(in演算子) -------------
// typeof以外での条件分岐方法
type NomadWorker = Engineer | Blogger;
// 型がNomadWorkerの関数を作る
function describeProfile(nomadWorker: NomadWorker) {
  console.log(nomadWorker.name);
  // nomadWorkerのキーにroleがあるかどうかで条件分岐する
  if ('role' in nomadWorker) {
    console.log(nomadWorker.role);
  }
  // nomadWorkerのキーにfollowerがあるかどうかで条件分岐する
  if ('follower' in nomadWorker) {
    console.log(nomadWorker.follower);
  }
}
// ------------- type guard(instanceof) -------------
class Dog {
  kind: 'dog' = 'dog'
  speak() {
    console.log('bow-wow');
  }
}
class Bird {
  kind: 'bird' = 'bird';
  speak() {
    console.log('tweet-tweet');
  }
  fly() {
    console.log('flutter');
  }
}
type Pet = Dog | Bird;
function havePet(pet: Pet) {
  pet.speak();
  switch (pet.kind) {
    case 'bird':
      pet.fly();
  }
  if (pet instanceof Bird) {
    pet.fly();
  }
}
havePet(new Bird());


// ------------- Optional Chaining -------------
//  あってもなくてもいい場合は?をつける
interface DownloadedData {
  id: number;
  user?: {
    name?: {
      first: string;
      last: string;
    }
  }
}

// DownloadedDataを型にもつ
const downloadedData: DownloadedData = {
  id: 1
}

// downloadedData.user?.nameは、
// downloadedData.userがundefinedもしくはnullだったら、undefinedを返す、
console.log(downloadedData.user?.name?.first);

// ------------- Nullish Coalescing -------------
const userData = downloadedData.user ?? 'no-user';
type id = DownloadedData["id"]

enum Color {
  RED,
  BLUE
}
class AdvancedPerson {
  name: string = 'Peter'
  age: number = 35;
}
class AdvancedCar {
  name: string = 'Prius'
  age: number = 5;
}
let target = new AdvancedPerson();
let source = new AdvancedCar();
target = source;
function advancedFn(...args: readonly number[]) {
}

advancedFn(0, 1)
const milk = 'milk' as const;
let drink = milk;
const array = [10, 20] as const;
const peter = {
  name: 'Peter',
  age: 38
} as const;
type PeterType = typeof peter;

````