あるオブジェクトが Data型かどうか?を調べる

● instanceof 演算子を使用する方法

if (variable instanceof Date) {
  console.log('変数はDate型です。');
} else {
  console.log('変数はDate型ではありません。');
}

● Object.prototype.toString.call メソッドを使用する方法

if (Object.prototype.toString.call(variable) === '[object Date]') {
  console.log('変数はDate型です。');
} else {
  console.log('変数はDate型ではありません。');
}
No.2452
01/23 14:54

edit

配列の値(as const)からUnion型(合併型)を生成する

● 配列の値(as const)からUnion型(合併型)を生成する

以下のように配列から型を自動的に生成することができます。
このようにしておくことで配列に変更があった時に型の修正の必要がありません。

const STATUS_VALUES = ["productInCart", "productInCheckout", "productPurchased"] as const;
type Status = typeof STATUS_VALUES[number];    // "productInCart" | "productInCheckout" | "productPurchased"

● as const についておさらい

as constアサーション を行うと次のような制約をつけることができます。

1. 「値」や「配列やオブジェクトの全てのメンバ」が readonlyとなる。
2. Widening(型の拡大)がされない

・ 1. 「値」や「配列やオブジェクトの全てのメンバ」が readonlyとなる。

const pikachu = {
  name: "pikachu",    // readonly
  height: 0.4,    // readonly
  weight: 6.0,    // readonly
} as const;

・ 2. Widening(型の拡大)がされない

// string型
let hoge = "my-sample-text"

// "my-sample-text"型
let fuga = "my-sample-text" as const
No.2392
09/13 15:11

edit

TypeScript ジェネリックを使って定義された関数へ型を渡さないときの型推論

// 関数を定義
function getfirstMember<T>(list: T[]) {
  return list[0]
}

この関数に対して、型をアノテートしないで使用した場合は引数から型推論される

type User = {
  id: number
  age: number
  name: string
}

const users: User[] = [
  {
    id: 1,
    age: 22,
    name: "太郎",
  },
  {
    id: 2,
    age: 41,
    name: "花子",
  },
]

const resultA = getfirstMember(users) // resultAの型は User

const resultB = getfirstMember(["hoge", "fuga"])  // resultBの型は string

const resultC = getfirstMember([undefined, true, false]) // resultCの型は boolean|undefined

const resultD = getfirstMember(true) // エラー

const result = getfirstMember([() => {}, () => {}])  // resultEの型は () => void
No.2391
08/25 15:42

edit

TypeScript の Conditional Types

● TypeScript の Conditional Types (条件型)

条件型 は 以下のような三項演算子のような記述で型を定義します。(条件式に合致するときはX。それ以外はY。)

type MyType = 条件式 ? X : Y

条件式 にはいろいろな記述があります。 例えば

interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}
 
type MyType1 = Dog extends Animal ? number : string;
// これは以下 ↓ と同じです。
type MyType1 = number
 
type MyType2 = RegExp extends Animal ? number : string;
// これは以下 ↓ と同じです。        
type MyType2 = string
No.2390
08/25 12:07

edit

Typescript の ユーティリティータイプ

Typescript の 型をいい感じで変換できるのが、ユーティリティータイプです。

● Utility Types

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

● 覚えておくととても使えるTypescript の Utility Types

Pick<Type, Keys>: あるTypeの一部を取り出して新しい型にする
Omit<Type, Keys>: あるTypeの一部を削除して新しい型にする

Partial<Type>: あるTypeの全てのメンバをオプショナルにして新しい型にする
Required<Type>: あるTypeの全てのメンバを必須にして新しい型にする

Parameters<Type>: Type(関数の引数)から型を作成する
ReturnType<Type>: 関数の返り値の型で型を作成

Readonly<Type>: あるTypeReadOnlyな型にする
Record<Keys,Type>: 型を組み合わせてオブジェクトの型を作成

Exclude<Type, ExcludedUnion>: Typeの中から指定したUnion型を取り除いて、新しい型にする
Extract<Type, Union>: Typeの中から指定したUnion型を抜き取って、新しい型にする

引用 : TypeScriptのUtility Typesを理解して活用する - Qiita
【TypeScript】覚えておきたいUtility Types

No.2361
06/14 09:27

edit

enum

● enum to Union

enum StringEnum {
  Small = 'S',
  Medium = 'M',
  Large = 'L',
}

// 👇️ type ValuesUnion = "S" | "M" | "L"
type ValuesUnion = `${StringEnum}`;

// 👇️ type KeysUnion = "Small" | "Medium" | "Large"
type KeysUnion = keyof typeof StringEnum;

● get Enum from value

const getKeyFromValue = (
  enumObj: {},
  value: string | number,
): string | undefined =>
  (Object.entries(enumObj).find(
    (e) => isNaN(Number(e[0])) && e[1] === value,
  ) ?? [undefined])[0];

const getEnumFromValue = <T extends Record<string, string | number>>(
  enumObj: T,
  value: string | number,
) => {
  const key: keyof T | undefined = getKeyFromValue(enumObj, value);
  if (!key) return null;
  return enumObj[key] || null;
};

enum DayWeek2{
  SAN="日曜日",
  MON="月曜日",
  TUE="火曜日",
  WEN="水曜日",
  THU="木曜日",
  FRI="金曜日",
  SAT="土曜日",
}

type Maybe<T> = T | null;

const check_1:DayWeek2 = DayWeek2.SAT; // ✅ 宣言OK

const check_2:DayWeek2 = DayWeek2['SAT']; // ✅ 宣言OK

const check_3:DayWeek2 = "土曜日"; // ❌ 宣言NG

const check_:Maybe<DayWeek2> = getEnumFromValue(DayWeek2,"土曜日"); // ✅ 宣言OK

const check_4a:Maybe<DayWeek2> = getEnumFromValue(DayWeek2, "土曜日"); // ✅ 宣言OK
console.log( check_4a ); // 土曜日

const check_4b:Maybe<DayWeek2> = getEnumFromValue(DayWeek2, "土曜日hoge"); // ✅ 宣言OK
console.log( check_4b ); // null

No.2360
06/06 12:51

edit

typescript で 配列 からUnion 型

● typescript で 配列 からUnion 型

const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Currency = typeof currencies[number]; // type Currency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD"
No.2359
06/01 18:26

edit

typescript の widening と「const と readonly」の違い

● typescript の widening

こちらにとても上手な説明があります https://qiita.com/yamashin0616/items/f6f2405dba4570638228

(引用させていただきました。 ↑ )

// 例1 : constでLiteral Typesの型を宣言(Widening発生)
const foo: "foo" = "foo"; // Literal Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // WideningによりErrorにならない
// 例2 : letでLiteral Typesの型を宣言(Wideningが発生しない)
let foo: "foo" = "foo"; // Literal Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // 変数barの値は"foo"で固定されているため、Errorになる
// 例3 : as constでLiteral Typesの型を宣言(Wideningが発生しない)
const foo = "foo" as const; // as constで変数fooのLiteral Typesの型を宣言
let bar = foo; // 変数fooを変数barに代入
bar = "bar"; // 変数barの値は"foo"で固定されているため、Errorになる

const

一度定義した後の再代入を禁止する

const hoge1:number = 123;
hoge1 = 999;  // エラー

readonly

オブジェクト型のプロパティにreadonly修飾子をつけることで使用できる。つまりプロパティ以外には使用できない。
ただオブジェクト自体を再代入して書き換えることはできる

type User = {
  readonly id: number;
  readonly name: string;
};

let user01:User = {
  id: 1,
  name:"Taro Yamada",
}

// エラー:読み取り専用プロパティであるため、'id' に代入することはできません。
user01.id = 2;  

// OK
user01 = {
  id: 999,
  name:"Taro Nise",
}

参考 : https://bit.ly/3WzR70F

No.2266
12/22 11:21

edit

typescriptでコールバック関数の型

● typescriptでコールバック関数の型

TypeScript でコールバック関数の型定義をしたい場合は、call signature を付けた interface として定義すれば良い。関数もオブジェクトの一種だから。
interface callbackType{(argv :number) :void};

function func(callback:callbackType){
    ...
}

引用 : https://gist.github.com/nkmry/9300823

No.2225
10/12 09:27

edit

typescript の 合併型「Union Types」と交差型「Intersection Types」

● 合併型「Union Types」= OR

OR
指定した型のどれかにマッチすれば良い。

typeの場合

type DrinkOrFood = Drink | Food;

● 交差型「Intersection Types」 = AND

AND
指定した型の全てにマッチすれば良い。

typeの場合

type Drink AndFood = Drink & Food;

interfaceの場合

interface Drink AndFood extends Drink, Food {}

型ガード(例: data に x というプロパティがあるかどうか?)

  if ('x' in data) {
  }
No.2209
09/07 14:18

edit

typescript で オブジェクトの keys を map したときのエラーの対処方法

● typescript で オブジェクトの keys を map で回すと次のようなエラーがでます

interface MyData {
  id: number;
  name: string;
}

const myData: MyData=
  {
    id: 1,
    name: 'hoge',
  }

Object.keys(myData).map((key) => {
  console.log(myData[key]);    // ★ ここでエラー(TS7053)となります。
});

TS Playground
https://bit.ly/3KxxBgx

このようなエラーが表示されます

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'MyData'.
  No index signature with a parameter of type 'string' was found on type 'MyData'.(7053)

● 修正方法

Object.keys(myData).map((key) => {
  console.log(myData[key]);    // ★ ここでエラー(TS7053)となります。
});

 ↓ 次のように修正します

・keys が MyData の キーであることを保証する

(Object.keys(myData) as (keyof MyData)[]).map((key) => {
  console.log(myData[key]);
});

・Object.entries を使って value を直接取得する

Object.entries(myData).map(([key, value]) => {
  console.log( '● key, value' );
  console.log( `${key} : ${value}` );
})

・Object.keys が返すのは必ず string[] になります

https://stackoverflow.com/questions/59545011/object-with-generic-keys-in-typescript

● 関数 isPropertyを定義 するという読みやすい方法あります

MyInterface の メンバ名であることを保証する関数を作成します。
name , address, email は適宜書き換えること

function isProperty(value: string): value is (keyof MyInterface){
    return value === 'name' || value === 'address' || value === 'email';
}

引用 : https://qiita.com/rednes/items/61d477a193b08fac9fe8

No.2205
10/31 17:33

edit