원클릭으로
context-type-inference
Use when extracting values causes type errors. Use when callback types are wrong. Use when const assertions are needed.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when extracting values causes type errors. Use when callback types are wrong. Use when const assertions are needed.
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 | context-type-inference |
| description | Use when extracting values causes type errors. Use when callback types are wrong. Use when const assertions are needed. |
Separating a value from its context can cause type errors.
TypeScript infers types based on both the value AND where it's used. When you extract a value to a variable, you lose context, which can cause surprising type errors.
When extraction breaks types, restore context with:
annotations, const assertions, or satisfies.
Remember:
as const prevents wideningsatisfies preserves context with validationtype Language = 'JavaScript' | 'TypeScript' | 'Python';
function setLanguage(language: Language) { /* ... */ }
setLanguage('JavaScript'); // OK - context from parameter
let language = 'JavaScript'; // Inferred as string (widened)
setLanguage(language);
// ~~~~~~~~
// Argument of type 'string' is not assignable to 'Language'
The value was widened to string when extracted.
let language: Language = 'JavaScript';
setLanguage(language); // OK
The annotation provides the context.
const language = 'JavaScript';
// ^? const language: "JavaScript"
setLanguage(language); // OK
const variables get narrower types (literal types).
let language = 'JavaScript' as const;
// ^? let language: "JavaScript"
setLanguage(language); // OK
as const prevents widening even with let.
function panTo(where: [number, number]) { /* ... */ }
panTo([10, 20]); // OK - inferred as tuple from context
const loc = [10, 20];
// ^? const loc: number[] (array, not tuple!)
panTo(loc);
// ~~~
// Argument of type 'number[]' is not assignable to '[number, number]'
const loc: [number, number] = [10, 20];
panTo(loc); // OK
const loc = [10, 20] as const;
// ^? const loc: readonly [10, 20]
Note: as const makes it readonly. If the function expects a mutable tuple, this won't work:
panTo(loc);
// ~~~
// 'readonly [10, 20]' is not assignable to '[number, number]'
The function should accept readonly [number, number] if it doesn't mutate the input.
type Point = [number, number];
const capitals1 = { ny: [-73.7562, 42.6526], ca: [-121.4944, 38.5816] };
// ^? { ny: number[]; ca: number[]; } (arrays, not tuples)
const capitals2 = {
ny: [-73.7562, 42.6526],
ca: [-121.4944, 38.5816],
} satisfies Record<string, Point>;
// ^? { ny: [number, number]; ca: [number, number]; } (tuples!)
satisfies provides context while preserving precise types.
const capitals3: Record<string, Point> = capitals2;
capitals3.pr; // No error! Property 'pr' returns Point (but undefined at runtime)
// ^? Point
capitals2.pr;
// ~~
// Property 'pr' does not exist
satisfies keeps precise keys; annotation doesn't.
TypeScript infers callback parameter types from context:
// Types inferred from app.get declaration
app.get('/health', (request, response) => {
// ^? Request<...>
// ^? Response<...>
response.send('OK');
});
// Don't add redundant annotations:
app.get('/health', (request: express.Request, response: express.Response) => {
// Redundant and verbose
});
// Context lost when callback is extracted
const handler = (request, response) => {
// ^? any ^? any
response.send('OK');
};
// Fix: Add types
const handler: express.RequestHandler = (request, response) => {
// ^? Request ^? Response
response.send('OK');
};
const config = {
language: 'JavaScript' as const,
// ^? "JavaScript" (not string)
};
setLanguage(config.language); // OK
Without as const, config.language would be string.
const obj = {
settings: {
language: 'JavaScript',
version: 4,
}
} as const;
// ^? { readonly settings: { readonly language: "JavaScript"; readonly version: 4; } }
as const is deep - everything becomes readonly with literal types.
Pressure: "I'll use as Language to fix it"
Response: Type assertions bypass safety. Use const or satisfies instead.
Action: Use as const for literal narrowing, not as Type.
Pressure: "Why doesn't it work when I extract it?"
Response: Context was lost. Restore it explicitly.
Action: Add annotation, use const, or use satisfies.
anystring| Excuse | Reality |
|---|---|
| "It's the same value" | Same value, different context = different inferred type |
| "TypeScript should know" | TypeScript needs context to infer precise types |
"I'll use as to fix it" | Use as const or satisfies, not type assertions |
type Lang = 'JS' | 'TS';
declare function setLang(l: Lang): void;
// DON'T: Lose context
let lang = 'JS'; // string
setLang(lang); // Error
// DO: Annotation
let lang: Lang = 'JS';
// DO: const
const lang = 'JS'; // "JS"
// DO: const assertion
let lang = 'JS' as const; // "JS"
// For objects: satisfies
const cfg = { lang: 'JS' } satisfies Record<string, Lang>;
Context matters for type inference.
When you extract a value, you may lose type context. Restore it with type annotations, const declarations, as const assertions, or satisfies. Understand which tool fits each situation.
Based on "Effective TypeScript" by Dan Vanderkam, Item 24: Understand How Context Is Used in Type Inference.