【发布时间】:2019-01-11 23:17:07
【问题描述】:
我得到:
重载签名与函数 implementation.ts(2394) 不兼容
开启:
/** Iterate through an Array. */
export default function eachr<Value>(
subject: Array<Value>,
callback: IteratorCallback<typeof subject, number, Value>
): typeof subject
整个sn-p:
export interface IteratorCallback<Subject, Key, Value> {
(this: Subject, value: Value, key: Key, subject: Subject): void | boolean
}
/** Iterate through an Array. */
export default function eachr<Value>(
subject: Array<Value>,
callback: IteratorCallback<typeof subject, number, Value>
): typeof subject
/** Iterate through an Object. */
export default function eachr<RecordKey extends keyof any, Value>(
subject: Record<RecordKey, Value>,
callback: IteratorCallback<typeof subject, RecordKey, Value>
): typeof subject
/** Iterate through the subject. */
export default function eachr<RecordKey extends keyof any, Value>(
input: Array<Value> | Record<RecordKey, Value>,
callback: IteratorCallback<typeof input, RecordKey | number, Value>
): typeof input {
if (Array.isArray(input)) {
// Array
const subject = input as Array<Value>
for (let key = 0; key < subject.length; ++key) {
const value = subject[key]
if (callback.call(subject, value, key, subject) === false) {
break
}
}
} else {
// Object
const subject = input as Record<RecordKey, Value>
for (const key in subject) {
if (subject.hasOwnProperty(key)) {
const value = subject[key]
if (callback.call(subject, value, key, subject) === false) {
break
}
}
}
}
// Return
return input
}
我可以通过将其更改为:
/** Iterate through an Array. */
export default function eachr<Subject extends Array<Value>, Value>(
subject: Subject & Array<Value>,
callback: IteratorCallback<typeof subject, number, Value>
): typeof subject
但是,我不明白为什么要修复它。问题出在哪里,为什么这种改变会让问题消失?
更令我惊讶的是,如果我将相同的更改应用于纯对象迭代器函数,它会导致它失败:
/** Iterate through an Object. */
export default function eachrObject<
Subject extends Record<RecordKey, Value>,
RecordKey extends keyof any,
Value
>(
subject: Subject & Record<RecordKey, Value>,
callback: IteratorCallback<typeof subject, RecordKey, Value>
): typeof subject {
for (const key in subject) {
if (subject.hasOwnProperty(key)) {
const value = subject[key]
// above fails with: Element implicitly has an 'any' type because type 'Record<RecordKey, Value>' has no index signature.ts(7017)
// below fails with: Argument of type 'string' is not assignable to parameter of type 'RecordKey'.ts(2345)
if (callback.call(subject, value, key, subject) === false) {
break
}
}
}
return subject
}
而这有效:
/** Iterate through an Object. */
export default function eachrObject<RecordKey extends keyof any, Value>(
subject: Record<RecordKey, Value>,
callback: IteratorCallback<typeof subject, RecordKey, Value>
): typeof subject {
for (const key in subject) {
if (subject.hasOwnProperty(key)) {
const value = subject[key]
if (callback.call(subject, value, key, subject) === false) {
break
}
}
}
return subject
}
然而,这两种形式都适用于 Array 迭代器:
/** Iterate through an Array. */
export default function eachrArray<Subject extends Array<Value>, Value>(
subject: Subject & Array<Value>,
callback: IteratorCallback<typeof subject, number, Value>
): typeof subject {
for (let key = 0; key < subject.length; ++key) {
const value = subject[key]
if (callback.call(subject, value, key, subject) === false) {
break
}
}
return subject
}
/** Iterate through an Array. */
export default function eachrArray<Value>(
subject: Array<Value>,
callback: IteratorCallback<typeof subject, number, Value>
): typeof subject {
for (let key = 0; key < subject.length; ++key) {
const value = subject[key]
if (callback.call(subject, value, key, subject) === false) {
break
}
}
return subject
}
那么为什么更改为Subject extends Array<Value> 是重载区域迭代器兼容性所必需的,而Subject extends Record<RecordKey, Value> 却破坏了对象迭代器?
抱歉,这里的代码量太少了,这是我可以将其归结为的最小用例,其中包含所有考虑因素。
【问题讨论】:
标签: typescript