更新:包含 TS 3.7 版本 + 数组类型
你的意思是这样的吗?
TS 3.7+(数组中的通用类型参数现在可以是circular https://github.com/microsoft/TypeScript/pull/33050):
type RecNullValuesToOptional<T> = T extends Array<any>
? Array<RecNullValuesToOptional<T[number]>>
: T extends object
? NullValuesToOptional<{ [K in keyof T]: RecNullValuesToOptional<T[K]> }>
: T;
界面是必要的):
type RecNullValuesToOptional<T> = T extends Array<any>
? RecNullValuesToOptionalArray<T[number]>
: T extends object
? NullValuesToOptional<{ [K in keyof T]: RecNullValuesToOptional<T[K]> }>
: T;
interface RecNullValuesToOptionalArray<T>
extends Array<RecNullValuesToOptional<T>> {}
操场 https://www.typescriptlang.org/play/#code/C4TwDgpgBAcgrgGwQNQIYLhAzgFQPYDyYwAlngHboA8OAfFALxQEC2JwNANLIgqgEYIIAaQggsNWvQBkAKChQACqgBOpaopIBjANZceSAUNHjJUgNyzZoSAb6CRYiXUawK8Qw6ryoACgDeUADawlAk5FA6YngAZlA4ALoAXPEhCVAQAB7AEOQAJlhu5B4INGn0APxQ5BAAbhAqUCmhAL4AlEFRILHxCbK0ltbg0DDuvJKuOBnZuQXVvFBVNfWNKTiD4TkqMaha0ACCUP4+qClYwCrhAOaWCvxnF9dQAD7zSJYtQ7YAQq4laBhsPgiKQKNR9gMoAB6KFHKCnKDnS7kK7cfgVB7Iq4vN4IKCfWSbBo7PZQADCRx8Wkx11uUDyKUOr3IvDpEEZQQSdJiKRZLH4DU5OJZ71kBJs0AAIn9eADMLhCMQyJRSmSBlYJVAAEoQLT-dDy4FKsGlFxMKZZHL5Qr7FQqVAgKiocggWg+Ko6vWyg1AxWglW2+2OnBBPkClQJN0KNbTK1zPD8ABWuuA7rsct9IOV1ECITCES6PUSKU9+sBCqzJrKwkj+KjTXidMJ5C2JOgpe95aN-vQgYdkh8ltmNrt-Y7SAzFeNKrMR3FwygAFFXOOUD6pz3VerZDCoMAABYkQpHqCJuDnKAxPCNEhIc8XVD+qBgOAqMB4LDQYB4KAC4BbRF9zwAB3Pd9y-BdwjA6AAElJUXL5oAAMT4f9cgmc1Y2HKAE2TLRUwUKoLRma18xiBpmB8Qi4TzKDCziAhkigFDHytKgCHKfEqIbZYGh8NZLE1RckOvFhWIgPJXBYtDyCoRdty0CgL3ZJdXGOBRqSgAAiK88C0zgfAZOEES0-hVH038UlM1AAC8tPxAyFBUoJAhMsyVAs+5tIARzgTJ7JabhXKs3y-ICvoWksRTyGUgAmFJlyYdSoE0nS8D0xz6RSYLtPczyrLMuyHMHFIXMsnywoc4yQrgSqWgi8xoVhBoVGvbhUCgNgsCwa5ZCAA
测试类型:
interface A {
a: string;
b: string | null;
}
interface C {
c: string;
d: A | null;
e: A[];
f: number[] | null;
}
/*
type EFormatted = {
c: string;
e: {
a: string;
b?: string | null | undefined;
}[];
d?: {
a: string;
b?: string | null | undefined;
} | null | undefined;
f?: number[] | null | undefined;
}
=> type EFormatted is the "flattened" version of
type E and used for illustration purposes here;
both types E and EFormatted are equivalent, see also Playground
*/
type E = RecNullValuesToOptional<C>
用一些数据进行测试:
const e: E = {
c: "foo",
d: { a: "bar", b: "baz" },
e: [{ a: "bar", b: "qux" }, { a: "quux" }]
};
const e2: E = {
c: "foo",
d: { a: "bar", b: "baz" },
e: [{ b: "qux" }, { a: "quux" }]
}; // error, a missing (jep, that's OK)