首先,这只是一个打字稿问题。我不在乎js部分。
我的最终目标是键入一个带有投影对象的简单猫鼬查找。
把电影说成3个领域:
Movie.findOne({ year: { $gte: 1980, $lte: 1989 }, {isGood: -1}, function(err, movie) {
// Here I want ts compiler to understand that returned object does not have the isGood property
});
我希望以这种方式键入返回的对象(没有isGood属性,因为我们在投影对象中省略了它。
{
name: string,
email: string
}
现在我有以下代码:
type Diff<T, U> = T extends U ? never : T; // Remove types from T that are assignable to U
interface Test {
blob: number;
pop: number;
}
interface UserProfile {
id: string
email: string
image: string | null
isAdmin: boolean
username: string
reviews: string[],
test: Test
}
type ExcludedTypes<T, U> = {
[K in Exclude<keyof T, keyof U>]: T[K]
}
type PartialFrom<T> = {
[P in keyof T]?: number | PartialFrom<T[P]>;
}
const excludeFn = <K extends Record<string, any>, T extends PartialFrom<K>>(user: K, projection: T): ExcludedTypes<K, T> => {
const newUser: K = {
...user
};
Object.keys(projection).forEach((key) => {
delete newUser[key];
})
return user;
}
const full: UserProfile = {
id: "reareaz",
email: "rezrza",
image: null,
isAdmin: false,
username: "rezaraz",
reviews: ["test"],
test: {
blob: 1221,
pop: 122,
}
}
const projection = {
email: -1,
image: -1,
reviews: -1,
}
const filteredObject = excludeFn(full, projection);
interface PartialUserProfile {
id: string
isAdmin: boolean
username: string
}
// this is just used to test that filteredObject is properly typed
const ppp = (a: PartialUserProfile): void => { }
// it should fail because email is not in filtered object anymore
ppp(filteredObject);
因此,这里的目标是创建一个将完整对象作为第一个参数,部分对象并返回不在部分对象中的完整对象的字段的类型函数。
我的上述示例仅适用于一级属性:
有效:
const full = {
image: 'string',
isFalse: true
}
const projection = {
image: -1
}
// will not have image property
const filteredObject = excludeFn(full, projection);
不起作用:
const full = {
image: 'string',
pasta: {
isGood: true,
brand: 'mypastabrand'
}
}
const projection = {
pasta: {
isGood: -1
}
}
const filteredObject = excludeFn(full, projection);
这不起作用,因为我的类型是:
type ExcludedTypes<T, U> = {
[K in Exclude<keyof T, keyof U>]: T[K]
}
深度不超过一层,这就是我被困住的地方