Gré*_*EUT 2 interface typescript typescript-typings
我有一个描述 mongodb 数据库数据的打字稿接口,如:
interface Foo {
_id: string,
name: string,
fish: {
_id: string,
name: string,
},
}
Run Code Online (Sandbox Code Playgroud)
我有一种方法可以构建要插入数据库的数据,例如:
function pushNewFish() {
const obj: Foo = {
name: 'obiwan',
fish: {
name: 'kenobi',
},
};
// ...
}
Run Code Online (Sandbox Code Playgroud)
问题是:我没有实现_id特定于数据库的每个元素。
我有可能使用,Partial<Foo>但这不是我要找的。
我也有可能把 every_id: string变成_id ?: string,但感觉不对。
有没有办法做到:
interface FooDatabase { ... }
type Foo = Partial<'_id', FooDatabase>;
Run Code Online (Sandbox Code Playgroud)
? 谢谢
iY1*_*1NQ 10
如果只有某些_id字段应该是可选的,则定义一个新的实用程序类型,该类型仅将选定的键声明为可选:
type Optional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>
interface FooDatabase {
_id: number;
foo: string;
bar: string;
}
type Foo = Optional<FooDatabase, '_id'>
Run Code Online (Sandbox Code Playgroud)
递归解决方案(对于嵌套对象),其中相同单例类型的每个键都是可选的:
type Primitive = number | string | boolean | undefined | null | any[];
type Optional<T, K extends keyof T> = { [P in K]?: T[P] } & { [P in Exclude<keyof T, K>]: T[P] extends Primitive ? T[P] : Optional<T[P], keyof T[P] & K> };
Run Code Online (Sandbox Code Playgroud)
也许你想要这样的类型:
type PartialK<T, K extends PropertyKey = PropertyKey> =
Partial<Pick<T, Extract<keyof T, K>>> & Omit<T, K> extends infer O ?
{ [P in keyof O]: O[P] } : never;
Run Code Online (Sandbox Code Playgroud)
在这里,PartialK<T, K>就像Partial<T>但只对 中的键起作用K,其余部分不理会。所以PartialK<T, keyof T>或PartialK<T, PropertyKey>应该像Partial<T>. 只要T是没有索引签名、调用签名或构造签名的对象类型,这应该可以正常工作。我对条件类型做了一个小技巧,这样生成的对象类型就没有交集,就像这样:
type TestPartialK = PartialK<{ a: string, b: number, c: boolean }, "b" | "c">
/* type TestPartialK = {
b?: number | undefined;
c?: boolean | undefined;
a: string;
} */
Run Code Online (Sandbox Code Playgroud)
现在它只能在一层深层次上工作,看起来您的问题想要通过嵌套对象递归地执行此操作。所以这里是NestedPartialK<T, K>:
type NestedPartialK<T, K extends PropertyKey = PropertyKey> =
T extends Function ? T :
T extends Array<any> ? Array<NestedPartialK<T[number], K>> :
T extends object ? PartialK<{ [P in keyof T]: NestedPartialK<T[P], K> }, K> :
T;
Run Code Online (Sandbox Code Playgroud)
它PartialK在定义中使用;它不考虑函数和原语,并使用递归类型将数组映射到数组,将对象映射到对象。请注意,它不会迭代元组,但是部分元组无论如何都很奇怪,而且您的用例甚至没有提到数组,所以我并不担心那么多。让我们看看它是否适用于您的FooDatabase:
type Foo = NestedPartialK<FooDatabase, "_id">
/* type Foo = {
_id?: string | undefined;
foo: string;
bar: string;
tree: {
_id?: string | undefined;
again: {
_id?: string | undefined;
value: string;
};
};
} */
Run Code Online (Sandbox Code Playgroud)
在我看来很好。_id现在所有的道具都是可选的,其他的道具都保留了下来。好的,希望有帮助;祝你好运!