項目23 エイリアスを作成したら一貫してそれを使う
ある値に新しい名前をつけると、エイリアスを作成したことになる
エイリアスのプロパティ変更は、元の値にも反映される
ポインター型や参照型と同じ考え
code:ts
const place = {name: 'New York', latLng: 41.6868, -74.2692};
const loc = place.latLng;
エイリアスは制御フロー解析を困難にするため、扱いには注意が必要
注意深く使うことで、TyepScirptはコードをより良く理解し、エラーをより多く発見できるようになる
同じようなプロパティアクセスをなくすために、エイリアス(変数)を使う場合は、一貫して使用しないと思わぬエラーが発生する
エラーが発生するコード
boxに対して絞り込みを行っていないので、うまく型推論がされていない状態
code:ts
/** 座標 */
interface Coordinate {x: number;y: number;}
/** 境界矩形 */
interface BoundingBox {x: number, number;y: number, number;}
/** ポリゴン */
interface Polygon {exterior: Coordinate[];holes: Coordinate[][];bbox?: BoundingBox;}
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const box = polygon.bbox;
if (polygon.bbox) {
if (pt.x < box.x0 || pt.x > box.x1 ||
// ~~~ ~~~ 'box' is possibly 'undefined'
pt.y < box.y0 || pt.y > box.y1) {
// ~~~ ~~~ 'box' is possibly 'undefined'
return false;
}
}
}
エラーが発生しないコード
併せて、分割代入を使って命名に一貫性を持たせている
code:ts
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const {bbox} = polygon;
if (bbox) {
const {x, y} = bbox;
if (pt.x < x0 || pt.x > x1 || pt.y < y0 || pt.y > y1) {
return false;
}
}
}
関数呼び出しによって、プロパティの型の絞り込みが無効になりうることに注意する
関数によってプロパティに変更が加わる場合、TyepScirptは、関数がその型のリボリ込みを無効にしないと想定する
詳しくは項目48 健全性の罠を回避する
code:ts
function expandABit(p: Polygon) { /* ... */ }
polygon.bbox // (property) Polygon.bbox?: BoundingBox | undefined
if (polygon.bbox) {
polygon.bbox // (property) Polygon.bbox?: BoundingBox
expandABit(polygon);
polygon.bbox // (property) Polygon.bbox?: BoundingBox
}
プロパティよりも、ローカル変数における型の絞り込みを信頼する
ローカル変数をイミュータブルに扱い、変更を防ぐことで、型安全性も向上する
#TypeScript