Type-Safe Handling of unknown
Narrow unknown values before using them safely.
Type-Safe Handling of unknown is a free TypeScript Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Working Safely With unknown
Typing external data as unknown is only half the job. The other half is narrowing it to a concrete type before use. This lesson covers the main narrowing techniques.
function describe(v: unknown): string {
if (typeof v === 'string') return 'string: ' + v;
if (typeof v === 'number') return 'number: ' + v;
return 'other';
}
console.log(describe('hi'), describe(7), describe(true));Narrowing With typeof
The typeof guard is the simplest tool. It narrows unknown to primitive types: string, number, boolean, function, object, and more.
function double(v: unknown): number {
if (typeof v === 'number') {
return v * 2; // v is number here
}
return 0;
}
console.log(double(21), double('no'));Narrowing With instanceof
For class instances, use instanceof. It narrows unknown to the specific class, unlocking its methods and properties safely.
function handle(v: unknown): string {
if (v instanceof Date) {
return v.toISOString(); // v is Date
}
return 'not a date';
}
console.log(handle(new Date(0)));Narrowing With the in Operator
The in operator checks whether a property exists on an object, narrowing object-typed values. First confirm the value is a non-null object, then probe its keys.
function getName(v: unknown): string {
if (typeof v === 'object' && v !== null && 'name' in v) {
return String((v as { name: unknown }).name);
}
return 'anonymous';
}
console.log(getName({ name: 'Ada' }), getName(5));Custom Type Guards
A custom type guard is a function whose return type is value is T. When it returns true, TypeScript narrows the argument to T at the call site.
function isString(v: unknown): v is string {
return typeof v === 'string';
}
function shout(v: unknown): string {
return isString(v) ? v.toUpperCase() : '?';
}
console.log(shout('hey'), shout(9));Guards for Object Shapes
Custom guards shine for validating object shapes. Write one function that checks all required fields, and the rest of your code can trust the narrowed type.
type User = { id: number; name: string };
function isUser(v: unknown): v is User {
return typeof v === 'object' && v !== null &&
'id' in v && 'name' in v;
}
console.log(isUser({ id: 1, name: 'Sam' }), isUser({}));JSON.parse Returns unknown-Like Data
JSON.parse is typed to return any, which silently bypasses safety. Best practice: capture it as unknown and validate before trusting the shape.
function parseConfig(text: string): unknown {
return JSON.parse(text);
}
const raw = parseConfig('{"port":8080}');
console.log(typeof raw);Validating Parsed JSON
Combine JSON.parse with a type guard to safely transform untrusted text into a typed value. If validation fails, handle the error instead of trusting bad data.
type Config = { port: number };
function isConfig(v: unknown): v is Config {
return typeof v === 'object' && v !== null &&
'port' in v && typeof (v as any).port === 'number';
}
const data: unknown = JSON.parse('{"port":8080}');
if (isConfig(data)) console.log('Port:', data.port);Chaining Multiple Guards
For complex inputs, layer guards: check the broad shape first, then refine. Each guard narrows a little more, producing precise, safe types step by step.
function process(v: unknown): string {
if (Array.isArray(v)) {
if (v.every((x) => typeof x === 'string')) {
return v.join('-');
}
}
return 'invalid';
}
console.log(process(['a', 'b']), process([1, 2]));Throwing on Invalid Data
When validation fails for required data, throw. Combined with a never-returning failure helper, this keeps the happy path clean and well-typed.
function asNumber(v: unknown): number {
if (typeof v === 'number') return v;
throw new Error('Expected a number');
}
console.log(asNumber(42));
try { asNumber('x'); } catch (e) { console.log('rejected'); }Putting It Together
The full pattern: receive data as unknown, narrow with guards, then operate on the precise type. This is the safe boundary between the untyped outside world and your typed code.
type Point = { x: number; y: number };
function isPoint(v: unknown): v is Point {
return typeof v === 'object' && v !== null &&
'x' in v && 'y' in v;
}
const input: unknown = { x: 1, y: 2 };
if (isPoint(input)) console.log(input.x + input.y);Quick Check
Test your understanding of safely handling unknown.
Recap: Handling unknown
You learned to narrow unknown with:
typeoffor primitives,instanceoffor class instances.- The
inoperator for object properties. - Custom type guards returning
value is T. - Validating
JSON.parseresults before trusting them.
Next course: type assertions and casting.
function isNonEmpty(v: unknown): v is string {
return typeof v === 'string' && v.length > 0;
}
console.log(isNonEmpty('hi'), isNonEmpty(''));Frequently asked questions
Is the “Type-Safe Handling of unknown” lesson free?
Yes — the full text of “Type-Safe Handling of unknown” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Type-Safe Handling of unknown”?
Narrow unknown values before using them safely. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Type-Safe Handling of unknown” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Understanding unknown vs any
- The never Type and Impossible States
- The void Type in Functions
- Type-Safe Handling of unknown