首页 > 解决方案 > 提供投影对象时键入 mongoose findOne 查询

问题描述

首先,这是一个打字稿唯一的问题。我不关心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]
}

不超过一层深度,这就是我被困的地方

标签: javascripttypescripttypestyping

解决方案


推荐阅读