如何属性键入MikroORM FindOneOrFailOptions 参数提前收集
How to property type the MikroORM FindOneOrFailOptions parameter to collect it in advance
我正在做一个打字稿项目,在某些时候,我需要提前从 MikroORM 收集 FindOneOrFailOptions
参数。
代码要复杂得多,但我设法用更少的行复制了这个问题。
虽然这段代码没有问题:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
return await repository.findOneOrFail({ url }, { populate: ['profile'] });
}
}
下面一个因加注 TS2345: Argument of type '{ populate: string[]; }' is not assignable to parameter of type 'FindOneOrFailOptions<Provider, string>'.
而失败:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
const options = { populate: ['profile'] };
return await repository.findOneOrFail({ url }, options);
-------
}
}
嗯,果然解决方案应该是将 options
声明为 FindOneOrFailOptions<Provider, string>
。但是,如果我这样做,则会引发 TS2322: Type 'string' is not assignable to type 'never'.
:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
const options: FindOneOrFailOptions<Provider, string> = { populate: ['profile'] };
---------
return await repository.findOneOrFail({ url }, options);
}
}
此时我对如何进行有点迷茫。
我假设那里的 never
来自函数声明:
class EntityRepository<T extends AnyEntity<T>> {
findOneOrFail<P extends string = never>(where: FilterQuery<T>, options?: FindOneOrFailOptions<T, P>): Promise<Loaded<T, P>>;
}
然而,即使我像repository.findOneOrFail<string>(...)
一样使用这个函数,它仍然会产生同样的错误。
我认为必须有某种自动转换,就像我内联参数一样,即使没有 <string>
,它也很乐意毫无问题地接受它。这告诉我,我还没有确定它期望的确切类型,但我对这种类型可能是什么一无所知。
如何才能毫无问题地提前声明 options
参数?非常感谢!
它不能只键入 string
,如果我们允许,我们将失去类型安全性,因为可以使用任何字符串。它需要是具有实际值的字符串文字类型。对于您的特定用例,const 断言应该可以完成这项工作:
await repository.findOneOrFail({ url }, { populate: ['profile'] as const });
How can I have the options parameter declared in advance without any issue? Many thanks!
您不能真正预先定义它并期望任何类型的安全性,因为它与实际值没有关系 - 如果需要,您需要自己进行转换。或者将类型 arg 设置为 any
,这不是很好,但实际上它是您想要的最精确的描述,因为它禁用了填充提示的严格类型。这是在创建此类对象后允许设置更多填充提示的唯一方法。
const options: FindOneOrFailOptions<Provider, any> = { populate: ['profile'] };
options.populate.push('otherProp');
如果您只想创建对象并且知道它只会包含一项,则可以显式传递类型值。
const options: FindOneOrFailOptions<Provider, 'profile'> = { populate: ['profile'] };
如果你不提供第二个类型的参数,默认是 never
- 所以没有它你永远不能将任何东西传递给 populate
提示。
我正在做一个打字稿项目,在某些时候,我需要提前从 MikroORM 收集 FindOneOrFailOptions
参数。
代码要复杂得多,但我设法用更少的行复制了这个问题。
虽然这段代码没有问题:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
return await repository.findOneOrFail({ url }, { populate: ['profile'] });
}
}
下面一个因加注 TS2345: Argument of type '{ populate: string[]; }' is not assignable to parameter of type 'FindOneOrFailOptions<Provider, string>'.
而失败:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
const options = { populate: ['profile'] };
return await repository.findOneOrFail({ url }, options);
-------
}
}
嗯,果然解决方案应该是将 options
声明为 FindOneOrFailOptions<Provider, string>
。但是,如果我这样做,则会引发 TS2322: Type 'string' is not assignable to type 'never'.
:
class ProviderRepository {
public async findOneByUrl(url: string): Promise<Provider> {
const repository = /* is of type EntityRepository<Provider> */
const options: FindOneOrFailOptions<Provider, string> = { populate: ['profile'] };
---------
return await repository.findOneOrFail({ url }, options);
}
}
此时我对如何进行有点迷茫。
我假设那里的 never
来自函数声明:
class EntityRepository<T extends AnyEntity<T>> {
findOneOrFail<P extends string = never>(where: FilterQuery<T>, options?: FindOneOrFailOptions<T, P>): Promise<Loaded<T, P>>;
}
然而,即使我像repository.findOneOrFail<string>(...)
一样使用这个函数,它仍然会产生同样的错误。
我认为必须有某种自动转换,就像我内联参数一样,即使没有 <string>
,它也很乐意毫无问题地接受它。这告诉我,我还没有确定它期望的确切类型,但我对这种类型可能是什么一无所知。
如何才能毫无问题地提前声明 options
参数?非常感谢!
它不能只键入 string
,如果我们允许,我们将失去类型安全性,因为可以使用任何字符串。它需要是具有实际值的字符串文字类型。对于您的特定用例,const 断言应该可以完成这项工作:
await repository.findOneOrFail({ url }, { populate: ['profile'] as const });
How can I have the options parameter declared in advance without any issue? Many thanks!
您不能真正预先定义它并期望任何类型的安全性,因为它与实际值没有关系 - 如果需要,您需要自己进行转换。或者将类型 arg 设置为 any
,这不是很好,但实际上它是您想要的最精确的描述,因为它禁用了填充提示的严格类型。这是在创建此类对象后允许设置更多填充提示的唯一方法。
const options: FindOneOrFailOptions<Provider, any> = { populate: ['profile'] };
options.populate.push('otherProp');
如果您只想创建对象并且知道它只会包含一项,则可以显式传递类型值。
const options: FindOneOrFailOptions<Provider, 'profile'> = { populate: ['profile'] };
如果你不提供第二个类型的参数,默认是 never
- 所以没有它你永远不能将任何东西传递给 populate
提示。