如何为接受泛型数组的typescript函数添加类型

如何为接受泛型数组的typescript函数添加类型,typescript,Typescript,请参阅下面的代码示例-我想了解resetHistory接受的数组项类型的一些类型安全性,但它不会在我希望的地方创建类型错误!谢谢你的建议 类型参数={ 配置文件:{userId:string}; 主页:未定义; 设置:{tab:“密码”|“配置文件”}; }; //天真地尝试键入历史参数 函数重置历史记录( 历史记录:{name:K;params:params[K]}[] ) { // ... } 重置历史([ {name:“主页”,参数:未定义}, {name:“profile”,参数:{u

请参阅下面的代码示例-我想了解
resetHistory
接受的数组项类型的一些类型安全性,但它不会在我希望的地方创建类型错误!谢谢你的建议

类型参数={
配置文件:{userId:string};
主页:未定义;
设置:{tab:“密码”|“配置文件”};
};
//天真地尝试键入历史参数
函数重置历史记录(
历史记录:{name:K;params:params[K]}[]
) {
// ...
}
重置历史([
{name:“主页”,参数:未定义},
{name:“profile”,参数:{userId:“1234”},

{name:“settings”,params:{userId:“xxx”},//这里需要的是所有可能的配对的并集。我们可以使用映射类型创建它

type HistoryEntry = {
  [K in keyof Params]: Params[K] extends undefined 
      ? { name: K; params?: undefined; }
      : { name: K; params: Params[K]; }
}[keyof Params]
对于
Params
对象的每个键,可接受的值是一个对象,该对象的
名称与该键匹配,而
Params
与该键的
Params
值匹配。即
{name:K;Params:Params[K];}

我添加了一个条件检查
Params[K]extensed undefined
,允许您在
未定义的情况下完全忽略
Params
。因此您只需传递
{name:“homepage”}

我们的
resetHistory
函数不再是泛型函数。它接受一个数组,其中所有条目的类型都是
HistoryEntry

function resetHistory( history: HistoryEntry[] ) {
这给了我们想要的所有错误:

resetHistory([
  { name: "homepage" }, // ok
  { name: "profile", params: { userId: "1234" } }, // ok
  { name: "settings" }, // error: params is missing
  { name: "settings", params: { userId: "xxx" } }, // error: tab is missing from params
  { name: "settings", params: { tab: "password" } } // ok
]);

这里需要的是所有可能的配对的并集。我们可以使用映射类型创建它

type HistoryEntry = {
  [K in keyof Params]: Params[K] extends undefined 
      ? { name: K; params?: undefined; }
      : { name: K; params: Params[K]; }
}[keyof Params]
对于
Params
对象的每个键,可接受的值是一个对象,该对象的
名称与该键匹配,而
Params
与该键的
Params
值匹配。即
{name:K;Params:Params[K];}

我添加了一个条件检查
Params[K]extensed undefined
,允许您在
未定义的情况下完全忽略
Params
。因此您只需传递
{name:“homepage”}

我们的
resetHistory
函数不再是泛型函数。它接受一个数组,其中所有条目的类型都是
HistoryEntry

function resetHistory( history: HistoryEntry[] ) {
这给了我们想要的所有错误:

resetHistory([
  { name: "homepage" }, // ok
  { name: "profile", params: { userId: "1234" } }, // ok
  { name: "settings" }, // error: params is missing
  { name: "settings", params: { userId: "xxx" } }, // error: tab is missing from params
  { name: "settings", params: { tab: "password" } } // ok
]);