如何让TypeScript识别符合JSON类型的接口并自动适配函数参数?
如何让TypeScript识别接口属于兼容JSON的类型?
给定如下递归定义的JSON值类型:
type JSONValue = | string | number | boolean | null | JSONValue[] | {[key: string]: JSONValue}
场景是:我们定义了一个接口Foo、操作该接口的函数bar,还有一个接受JSONValue类型参数的wrap函数。调用wrap(bar, {name: 'FOO', fooProp: 'hello'})时,TypeScript会抛出类型不兼容错误:
Argument of type '(foo: Foo) => Foo' is not assignable to parameter of type '(...args: JSONValue[]) => JSONValue'. Types of parameters 'foo' and 'args' are incompatible. Type 'JSONValue' is not assignable to type 'Foo'. Type 'null' is not assignable to type 'Foo'.
尽管我们知道传入的参数完全符合JSON兼容结构,但TS无法自动识别接口Foo属于JSONValue的子类型。以下是几种可行的解决方式:
1. 用工具类型约束并断言类型
先定义一个工具类型,用来验证类型是否兼容JSONValue:
type IsJSONCompatible<T> = T extends JSONValue ? T : never;
之后在调用wrap时,通过类型断言明确告知TS:bar的参数和返回值都是兼容JSON的类型:
interface Foo { name: string; fooProp: string; } const bar = (foo: Foo): Foo => ({...foo}); function wrap(fn: (...args: JSONValue[]) => JSONValue, ...args: JSONValue[]): JSONValue { return fn(...args); } // 使用类型断言转换bar的类型 wrap(bar as (foo: IsJSONCompatible<Foo>) => IsJSONCompatible<Foo>, {name: 'FOO', fooProp: 'hello'});
2. 定义递归工具类型转换接口为JSON兼容类型
如果接口嵌套层级较深,可以用递归工具类型自动转换所有属性为JSON兼容类型:
type ToJSONCompatible<T> = T extends JSONValue ? T : T extends object ? {[K in keyof T]: ToJSONCompatible<T[K]>} : never; // 转换Foo为JSON兼容类型 type FooJSON = ToJSONCompatible<Foo>; // 断言bar接受并返回FooJSON类型 wrap(bar as (foo: FooJSON) => FooJSON, {name: 'FOO', fooProp: 'hello'});
3. 结合类型守卫做运行时+编译时双重校验
如果需要更安全的校验,可以写一个类型守卫函数,在运行时验证输入是否符合Foo结构,同时让TS在编译时识别类型:
function isFoo(value: JSONValue): value is Foo { return ( typeof value === 'object' && value !== null && typeof (value as Foo).name === 'string' && typeof (value as Foo).fooProp === 'string' ); } const input = {name: 'FOO', fooProp: 'hello'}; if (isFoo(input)) { // 此时TS已确认input是Foo类型,再通过断言传递给wrap wrap(bar as (foo: JSONValue) => JSONValue, input); }
核心原因
TypeScript不会自动推断接口是JSONValue的子类型,因为JSONValue是递归联合类型,TS不会主动遍历接口的所有属性来验证其是否完全符合JSON结构。必须通过工具类型、断言或类型守卫,手动向TS声明接口的JSON兼容性。
内容的提问来源于stack exchange,提问作者theahura
相关产品推荐
相关产品推荐

