項目40 正確でない型より精度の低い型を選択する
型の精度の高さは、バグの発見やTypeScriptのサポートを受けれるので良いが、注意が必要
型の精度を高める過程で、誤った型を定義してしまい、間違った型が生まれることがある
型の精度を高めた結果、型を不正確にしてしまう例
code:ts
interface Point {type: 'Point'; coordinates: number[];}
interface LineString {type: 'LineString'; coordinates: number[][];}
interface Polygon {type: 'Polygon'; coordinates: number[][][];}
type Geometry = Point | LineString | Polygon;
Pointのcoordinatesは座標を表すため、number[]は精度に欠けるため、[number, number]にした結果、不正確になってしまった
code:ts
interface Point {type: 'Point';coordinates: GeoPosition;}
interface LineString {type: 'LineString'; coordinates: GeoPosition[];}
型安全性の不気味の谷を避ける。複雑で不正確な型は、シンプルで精度の低い型よりも悪いことが多い 型を正確にモデリングできないときは、不正確なモデルを採用しないこと
ギャップを受け入れ、anyやunknownを使用する
code:ts
12
"red"
1, 2 // 3
20, 2 // 10
["case", 20, 10, "red", "blue"] // "red"
上記の値を表現する型を定義する
code:ts
type Expression2 = number | string | any[];
const okExpressions: Expression2[] = [
10,
"red",
10, 5,
["case", 20, 10, "red", "blue"],
];
const invalidExpressions: Expression2[] = true // 型エラーになる 型の精度を向上させる際、エラーメッセージやオートコンプリートにも注意をはらい、開発体験にも気を配る
code:ts
type Expression4 = number | string | CallExpression;
type CallExpression = MathCall | CaseCall | RGBCall;
type MathCall = [
'+' | '-' | '/' | '*' | '>' | '<',
Expression4,
Expression4,
];
interface CaseCall {
0: 'case';
length: 4 | 6 | 8 | 10 | 12 | 14 | 16; // などなど
}
const okExpressions: Expression4[] = [
10,
"red",
10, 5,
["case", 20, 10, "red", "blue"],
];
const invalidExpressions: Expression4[] = [
["case", 20, 10, "red", "blue", "green"],
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Types of property 'length' are incompatible.
// プロパティ 'length' の型に互換性がありません。
// Type '5' is not assignable to type '4 | 6 | 8 | 10 | 12 | 14 | 16'.
// 型 '5' を型 '4 | 6 | 8 | 10 | 12 | 14 | 16' に割り当てることはできません。
];
複雑なコードはより多くのテストコードを必要するのと同様に、複雑な方にも多くのテストコードが必要になる