有没有一种方法在 TypeScript 中将泛型类型限制为仅限于普通对象?

11
使用TypeScript,有没有一种方法可以限制泛型类型仅允许对象类型的值?不包括数组和其他类型。
例如:
function check<O extends object>(ob: O): O {
  return ob
}

check({}) // should be fine
check([]) // should show error, but does not.

一个可能的现实世界的使用案例:
function extend<A extends object, B extends object>(a: A, b: B): A & B {
  return {
    ...a,
    ...b,
  };
}

// This is fine, return type is { x: number } & { y: string }
extend({x: 5}, {y: "str"})

// This should not be allowed
// Return type is number[] & string[]
// Accessing a property yields impossible types like number & string
extend([1,2,3], ["s", "i", "d"])

// More examples for variants which I don't want to allow
extend({}, function() {})
extend({}, new Map())

这其实很有趣,因为每个数组也是一个对象。 - Jonas Wilms
2个回答

6

如果O扩展了any[],您可以使用条件类型向参数的参数添加内容。添加的内容可以确保调用将产生错误。我通常会添加字符串字面类型,并将它们视为自定义错误消息:

function check<O extends object>(ob: O & (O extends any[] ? "NO Arrays !" : {})): O
function check<O extends object>(ob: O): O {
  return ob
}

check({}) // should be fine
check([]) // error

不错,我也想到了类似的东西,但我没有想到使用联合类型,这使得整个东西更加优雅。 - Jonas Wilms
很好,你需要重载的原因是什么?只使用第一个签名似乎已经可以正常工作了。 - bugs
这只适用于数组。我试图避免任何不是普通对象的类型。 - sidoshi
2
@bugs 条件语句的交集可能会干扰其他内容,虽然这个简单的例子不会出现问题,但我认为最好将条件签名分开,你也可以只使用一种类型来完成它。 - Titian Cernicova-Dragomir
1
@sidoshi TypeScript不支持__proto__,因此它没有关联的类型(实际上使用它是一个错误)。我也考虑过constructor,但它被定义为Function类型。 - Titian Cernicova-Dragomir
显示剩余4条评论

4
在更新版本的Typescript中,您可以使用object & Exclude<T, any[]>来表示一个不能是数组的对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接