원클릭으로
consistent-aliases
Use when narrowing doesn't work as expected. Use when using variables for object properties. Use when refinements are lost.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when narrowing doesn't work as expected. Use when using variables for object properties. Use when refinements are lost.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when defining global types. Use when augmenting window. Use when typing environment variables. Use when working with build-time constants. Use when configuring type definitions.
Use when migrating JavaScript to TypeScript. Use when gradually adopting TypeScript. Use when working with mixed codebases. Use when converting large projects. Use when teams are learning TypeScript.
Use when writing asynchronous code. Use when tempted to use callbacks. Use when composing multiple async operations.
Use when creating types from example data. Use when types don't match all cases. Use when API responses vary.
Use when writing type annotations on variables. Use when TypeScript can infer the type. Use when code feels cluttered with types.
Use when defining array-like types. Use when tempted to use number as index type. Use when understanding array keys.
| name | consistent-aliases |
| description | Use when narrowing doesn't work as expected. Use when using variables for object properties. Use when refinements are lost. |
If you create an alias, use it consistently.
When you assign an object property to a variable, you create an alias. TypeScript tracks them separately, so narrowing one doesn't narrow the other. Choose one and stick with it.
One alias OR the original - never mix them in the same scope.
Prefer destructuring for consistent naming.
Remember:
interface Polygon {
exterior: Coordinate[];
bbox?: BoundingBox;
}
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const box = polygon.bbox; // Created an alias
if (polygon.bbox) { // Narrows polygon.bbox
if (pt.x < box.x[0]) { // box is still possibly undefined!
// ~~~
// 'box' is possibly 'undefined'
}
}
}
The check on polygon.bbox doesn't narrow box.
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const box = polygon.bbox;
if (box) { // Check the alias
if (pt.x < box.x[0]) { // Use the alias
// OK - box is narrowed here
}
}
}
Now both the check and usage refer to the same variable.
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const { bbox } = polygon; // Same name as property
if (bbox) {
const { x, y } = bbox; // Continue destructuring
if (pt.x < x[0] || pt.x > x[1] || pt.y < y[0] || pt.y > y[1]) {
return false;
}
}
return true;
}
Benefits:
box vs bbox confusion)Aliasing affects runtime behavior:
const { bbox } = polygon;
if (!bbox) {
calculatePolygonBbox(polygon); // Fills in polygon.bbox
// Now polygon.bbox exists, but bbox is still undefined!
}
The alias and original can diverge at runtime.
TypeScript makes a pragmatic choice about function calls:
function expandPolygon(p: Polygon) { /* ... */ }
if (polygon.bbox) {
polygon.bbox // BoundingBox (narrowed)
expandPolygon(polygon);
polygon.bbox // Still BoundingBox (TypeScript trusts you)
// But the function might have set it to undefined!
}
TypeScript assumes functions don't invalidate refinements. This is usually fine but can be wrong.
if (polygon.bbox) {
const bbox = polygon.bbox; // Capture it locally
expandPolygon(polygon);
bbox // Still BoundingBox - local variable is safe
}
Local variables can't be changed by function calls.
function safeExpand(p: Readonly<Polygon>) {
// Can't modify p.bbox
}
if (polygon.bbox) {
safeExpand(polygon);
polygon.bbox // Guaranteed still BoundingBox
}
Readonly parameters prevent mutation concerns.
// Instead of:
const name = person.nickname;
const displayName = name ? name : person.fullName;
// Use:
const displayName = person.nickname ?? person.fullName;
// TypeScript doesn't connect has() and get():
if (map.has(key)) {
const value = map.get(key); // Still T | undefined
}
// Better pattern:
const value = map.get(key);
if (value !== undefined) {
value // T (narrowed)
}
// Or with nullish coalescing:
const value = map.get(key) ?? defaultValue;
Pressure: "Sometimes I use the property, sometimes the variable"
Response: Pick one. Mixing them breaks narrowing.
Action: Use destructuring for consistent naming.
Pressure: "I know expandPolygon doesn't touch bbox"
Response: TypeScript can't know that. Document with Readonly.
Action: Use local variables or readonly parameters for safety.
if check| Excuse | Reality |
|---|---|
| "The alias is the same thing" | TypeScript tracks them separately |
| "I already checked the property" | Check doesn't narrow the alias |
| "Functions won't mutate it" | TypeScript can't verify that |
// DON'T: Mix alias and original
const box = polygon.bbox;
if (polygon.bbox) { // Checks original
box.x; // Uses alias - still possibly undefined!
}
// DO: Use alias consistently
const box = polygon.bbox;
if (box) { // Checks alias
box.x; // Uses alias - narrowed correctly
}
// DO: Use destructuring
const { bbox } = polygon;
if (bbox) {
const { x, y } = bbox;
}
Choose one name and use it consistently.
When you alias a property, TypeScript tracks the alias and original separately. Narrowing one doesn't narrow the other. Use destructuring for consistent naming, and prefer local variables when function calls might invalidate refinements.
Based on "Effective TypeScript" by Dan Vanderkam, Item 23: Be Consistent in Your Use of Aliases.