Open6
TypeScript/JavaScript TIPS

アンチパターン?
as
の乱用
型安全でない.a: number | string に,a as number とした場合,number として扱われるが,実際には string かもしれないということが起こる.極力使わない方がいいかもしれない.
object同士のUnion型
オブジェクト同士のUnion型は型判別が難しい.typeof による型判別は使えない,どっちもobject型になる.’hoge’ in obj のように in 演算子を使って,objにプロパティが存在するか確認できるが,objectによっては,型を完全に識別できない場合がある.number | string のように,primitive型のUnion型なら,typeof で識別できるから問題ない.

object同士のUnion型の型判別
objectに,type プロパティをリテラル型で持たせるパターンがよく使われるらしい.
interface A {
type: "A",
a: string,
}
interface B {
type: "B",
b: number,
}
type AB = A | B
const obj: AB = {
type: "A",
a: string,
}
switch (obj.type) {
case "A":
…
case "B":
…
}

type と interface どちらを使うべき?
class を使用しない環境(Next.jsなど)では,type で十分なら type を使う.
class を使用する環境(NestJSなど)では,interface を積極的に使うべき.

hoge? より hoge | undefined を使ってプロパティを定義した方が安全
hoge? だと,宣言がなくてもエラーにならないけど,hoge | undefined の場合は,宣言が無いとエラーになる.宣言が明示的でわかりやすいらしい.
// ×
interface Hoge {
hoge? : string;
fuga: number;
};
const h: Hoge = {
fuga: number;
}
// ◯
interface Hoge {
hoge : string | undefined;
fuga: 3;
};
// エラー
const h: Hoge = {
fuga: number
}
// hoge を宣言する必要がある
const h: Hoge = {
hoge: undefined;
fuga: 3;
}

テンプレートリテラル型便利そう
type money = `${number}円`;
const a: money = '100円';
const b: money = '200円';
const c: money = '300円';
const d: money = '百円'; // Error: Type '"百円"' is not assignable to type 'money'.
const e: money = '100'; // Error: Type '"100"' is not assignable to type 'money'.

any 使わず,unknown 使う
any のようななんでも受け入れる型を使いたくなったら,any で妥協する前に,unknown が使えないか確認した方がよさそう.unknown は,なんでも受け入れる型だが,できることが制限されていて,安全に使える.