【发布时间】:2022-01-18 22:34:33
【问题描述】:
假设给定类型:
export declare type MongoManagerFilter<T> = {
[P in keyof T]?: (P extends keyof T ? T[P] : any);
};
尝试指定过滤器时:
update.$setOnInsert.createdAt = new Date();
我收到此错误:
Type 'Date' is not assignable to type '"createdAt" extends keyof T ? T[keyof T & "createdAt"] : any'.ts(2322)
但如果我将过滤器更改为此它可以工作:
export declare type MongoManagerFilter<T> = {
[P in keyof T]?: any;
};
为什么条件语句实际上并没有弄清楚类型?它只是将代码保留为类型。
我知道过滤器没有意义,我有另一种类型而不是 keyof T 来捕获点表示法,但我遇到了同样的问题,条件语句无法确定实际类型。
完整示例
interface CollectionDocument {
_id?: string;
createdAt: Date;
}
type PathImpl<T, Key extends keyof T> =
Key extends string
? T[Key] extends Record<string, any>
? `${Key}.${PathImpl<T[Key], Exclude<keyof T[Key], keyof Date | keyof Object | keyof string> & string>}`
| `${Key}.${Exclude<keyof T[Key], keyof Date | keyof Object | keyof string> & string}`
: never
: never;
type Path<T> = keyof T | PathImpl<T, keyof T>;
type PathValue<T, P extends Path<T>> =
P extends `${infer Key}.${infer Rest}`
? Key extends keyof T
? Rest extends Path<T[Key]>
? PathValue<T[Key], Rest>
: never
: never
: P extends keyof T
? T[P]
: any;
export declare type MongoManagerFilter<T> = {
[P in Path<T>]?: PathValue<T, P>;
};
export class MongoManagerCollection<T extends CollectionDocument> {
constructor() {}
updateOne(filter: MongoManagerFilter<T>) {
// THIS DOES NOT WORK
filter._id = '';
filter.createdAt = new Date();
}
}
// THIS WORKS
let testModel = new MongoManagerCollection<CollectionDocument>();
testModel.updateOne({_id: 'test', createdAt: new Date()});
编辑 向这个游乐场添加另一层以解决更多问题:
由于类型的递归,我似乎也遇到了这个错误:
Type instantiation is excessively deep and possibly infinite.ts(2589)
【问题讨论】:
-
请提供minimal reproducible example,清楚地表明您面临的问题。理想情况下,有人可以将代码放入像The TypeScript Playground (link here!) 这样的独立 IDE 中,然后立即着手解决问题,而无需首先重新创建它。所以不应该有伪代码、拼写错误、不相关的错误或未声明的类型或值。
-
正在处理中
-
感觉像一个错误,虽然我真的不明白你打算用这种情况做什么。如果
P是T的一个键,那么P什么时候不会从T扩展一个键?感觉条件总是为真,因此相当于[P in keyof T]?: T[P];。这会很好。我知道你写了“我知道过滤器没有意义”,但它很难帮助你找出问题。 -
我会调整它以添加点符号
标签: typescript typescript-typings typescript-generics