Learn why TypeScript throws TS2571 when you try to use a value typed as 'unknown' without narrowing it first, and how to safely narrow unknown types.
TypeScript error TS2571 means you are trying to use a value of type unknown as if it were a more specific type. The unknown type was introduced in TypeScript 3.0 as a type-safe alternative to any — it represents a value that could be anything, but unlike any, TypeScript will not let you do anything with it until you narrow it down.
Think of unknown as TypeScript saying: "I know this value exists, but I have no idea what it is. Prove to me what type it is before you try to use it."
This error most commonly appears when working with:
useUnknownInCatchVariables)With strict mode or useUnknownInCatchVariables enabled, catch clause variables are typed as unknown instead of any.
// ❌ Error: Object is of type 'unknown'. (TS2571)
try {
await fetchUserData()
} catch (error) {
console.log(error.message) // Can't access .message on unknown
}// ✅ Narrow the error type first
try {
await fetchUserData()
} catch (error) {
if (error instanceof Error) {
console.log(error.message) // Safe — error is narrowed to Error
} else {
console.log('An unexpected error occurred:', String(error))
}
}JSON.parse returns any by default, but if you assign it to a variable typed as unknown (or if a wrapper function returns unknown), you cannot use it directly.
function safeJsonParse(text: string): unknown {
return JSON.parse(text)
}
// ❌ Error: Object is of type 'unknown'. (TS2571)
const config = safeJsonParse(rawText)
console.log(config.port)// ✅ Validate and narrow the type
interface AppConfig {
port: number
host: string
}
function isAppConfig(value: unknown): value is AppConfig {
return (
typeof value === 'object' &&
value !== null &&
'port' in value &&
'host' in value
)
}
const config = safeJsonParse(rawText)
if (isAppConfig(config)) {
console.log(config.port) // Safe — config is narrowed to AppConfig
}When a generic type parameter defaults to or resolves to unknown, any operations on that value will trigger TS2571.
// ❌ Error: Object is of type 'unknown'. (TS2571)
function processResponse(data: unknown) {
return data.trim() // Can't call .trim() on unknown
}// ✅ Use typeof to narrow primitives
function processResponse(data: unknown) {
if (typeof data === 'string') {
return data.trim() // Safe — data is narrowed to string
}
throw new Error('Expected a string response')
}Some utility types and data structures can produce unknown values.
const metadata = new Map<string, unknown>()
metadata.set('version', '2.0.1')
// ❌ Error: Object is of type 'unknown'. (TS2571)
const version = metadata.get('version')
console.log(version.split('.'))// ✅ Narrow after retrieving the value
const version = metadata.get('version')
if (typeof version === 'string') {
console.log(version.split('.'))
}typeof checks — for primitive types like string, number, and boolean, a simple typeof check narrows the type:if (typeof value === 'string') {
// value is string here
}instanceof checks — for class instances like Error, Date, or custom classes:if (value instanceof Error) {
console.log(value.message)
}function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'email' in value
)
}as. This trades safety for convenience:const config = loadConfig() as AppConfigunknown values into typed data safely and give you runtime validation for free.TS2571 occurs when you try to access properties, call methods, or perform operations on a value typed as unknown without first narrowing it to a more specific type. TypeScript requires you to prove what the value is before it lets you use it. This commonly happens with catch clause variables, JSON parse results, and values received from external sources.
Narrow the unknown value to a specific type before using it. The approach depends on what you expect the value to be: use typeof for primitives (string, number, boolean), instanceof for class instances (Error, Date), or write a custom type guard function for object shapes. As a last resort, you can use a type assertion (as MyType), but this skips runtime safety.
any and unknown?Both any and unknown can hold any value, but they have opposite safety profiles. With any, TypeScript turns off all type checking — you can access any property, call any method, and assign it to any type without errors. With unknown, TypeScript blocks all operations until you narrow it to a specific type. This makes unknown the type-safe choice when you genuinely do not know what a value will be. Use unknown when you want safety, and avoid any whenever possible.
Get the latest TypeScript tips, tutorials, and course updates delivered straight to your inbox.