Typescript函数定义,以确保第二个参数与第一个参数的类型相同

时间:2019-07-04 08:46:37

标签: typescript

假设我具有此功能(忽略它的目的,这只是一个基本示例):

const doSomething = (object1, object2) => {
  return { ...object1, ...object2 }
}

如果object2必须与object具有相同的类型,我该如何编写类型定义?

例如,

interface DefaultObject {
  foo: number,
  other?: string
}

const object1: DefaultObject = {
  foo: 1
}

// :::::::::::::::::::::::::::::::::::

const object2 = {
  other: "something"
}
doSomething(object1, object2)

// this should error as object2 does not contain the required 'foo' key/value pair

// :::::::::::::::::::::::::::::::::::

const object3 = {
  foo: "1"
}
doSomething(object1, object3)

// this should error as object3's 'foo' value is not a number 

// :::::::::::::::::::::::::::::::::::

const object4 = {
  foo: 2,
  bar: 2
}
doSomething(object1, object4)

// this should error as object2 contains an extra 'bar' key/value pair

// :::::::::::::::::::::::::::::::::::

const object5 = {
  foo: 2
}
doSomething(object1, object5)

// this should pass as both objects have the same DefaultObject type 

// :::::::::::::::::::::::::::::::::::

1 个答案:

答案 0 :(得分:1)

您可以向函数广告添加通用类型参数,以同时将其用于object1object2

const doSomething = <T,>(object1: T, object2: T) => { // comma for tsx files
  return { ...object1, ...object2 }
}

修改

您的第4个测试有效,因为具有额外属性的类型是DefaultObject的子类型,因此可以将其分配给期望使用DefaultObject引用的位置。

如果第二个参数上存在任何额外的键,则可以使用条件类型来强制错误:

const doSomething = <T, U extends T>(object1: T, object2: U & (keyof U extends keyof T ? {} : "No etxra keys")) => { // comma for tsx files
  return { ...object1, ...object2 }
}

Playground link