我正在尝试为以下函数进行正确的输入:
export function filter(obj: any, predicate: (value: any, key: string) => boolean) {
const result: any = {};
Object.keys(obj).forEach((name) => {
if (predicate(obj[name], name)) {
result[name] = obj[name];
}
});
return result;
}
Run Code Online (Sandbox Code Playgroud)
是否可以保留打字内容?
如果没有有关用例的更多具体信息,我倾向于这样做:
function filter<T extends object>(
obj: T,
predicate: <K extends keyof T>(value: T[K], key: K) => boolean
) {
const result: { [K in keyof T]?: T[K] } = {};
(Object.keys(obj) as Array<keyof T>).forEach((name) => {
if (predicate(obj[name], name)) {
result[name] = obj[name];
}
});
return result;
}
Run Code Online (Sandbox Code Playgroud)
我们想要filter()
接受泛型类型obj
的参数,这意味着您将只过滤对象类型而不是基元,并且您希望编译器跟踪实际的键值关系,而不是将其一直扩展到。因此,回调需要接受适用于 的参数;因此我们将其设为参数类型的通用回调,其中是对应的属性值类型。有关该表示法的更多信息,请参阅查找类型的文档。T extends object
T
object
predicate
value
key
T
K extends keyof T
key
value
T[K]
keyof
对于结果,我们希望返回一个属性与 相同T
但可选的对象,因为我们不知道哪些属性实际上存在。这可以表示为映射类型 { [K in keyof T]? T[K] }
,也称为Partial<T>
。
一个问题是我必须使用类型断言来告诉编译器我期望Object.keys(obj)
是Array<keyof T>
( 的键的数组T
)而不仅仅是string[]
。这个期望可能会被违反,这就是为什么首先Object.keys()
返回;string[]
请参阅另一个 SO 问题以获取对此的解释。我认为在这里做出这个假设是合理的,但我将向您展示一种如果违反假设可能导致运行时错误的方法。
首先让我们测试所需的行为:
const obj = filter({ a: "hello", b: 123, c: true }, (v, k) => k === "b");
/* const obj: {
a?: string | undefined;
b?: number | undefined;
c?: boolean | undefined;
} */
console.log(obj); // {b: 123}
Run Code Online (Sandbox Code Playgroud)
看起来不错; 编译器对参数感到满意,filter()
并返回带有可选属性的值。
这是糟糕的情况:
interface Foo {
x: string,
y: string,
}
interface Bar extends Foo {
z: number;
}
const bar: Bar = { x: "hello", y: "goodbye", z: 100 };
const foo: Foo = bar; // acceptable because Bar extends Foo
filter(foo, (v, k) => v === v.toLowerCase() ); // compiles fine, but
// RUNTIME TypeError: v.toLowerCase is not a function
Run Code Online (Sandbox Code Playgroud)
编译器没有意识到foo
具有number
-valued 属性,因为我们已经扩展bar
到Foo
,但predicate
回调实际上依赖v
于string
. 编译后,您会收到运行时错误。如果您担心这种可能性,那么您可能需要更严格的类型来filter()
强制predicate
真正采用 type 的值(value: unknown, key: PropertyKey)
,但这使用起来会更烦人。这实际上取决于用例。
归档时间: |
|
查看次数: |
4259 次 |
最近记录: |