Typescript 元组成员的类型脚本类型解析-为什么编译? 游乐场

Typescript 元组成员的类型脚本类型解析-为什么编译? 游乐场,typescript,types,discriminated-union,Typescript,Types,Discriminated Union,给定以下类型定义: type State=[“IDLE”]|[“STARTING_NEW_CONVERSATION”]|[“CHANNEL_ACTIVE”、“synched”|“EXPLORING”]; 常量状态:状态=。。。 以及以下帮助器方法: 导出函数匹配( 值:T, 检查:T[0], 检查2?:摘录[1] ) { 返回值[0]==check&(check2?值[1]==check2:true); } //另一个变体。。。 导出函数匹配( 值:T, 检查:T[0], 检查2:T扩展[推断

给定以下类型定义:

type State=[“IDLE”]|[“STARTING_NEW_CONVERSATION”]|[“CHANNEL_ACTIVE”、“synched”|“EXPLORING”];
常量状态:状态=。。。
以及以下帮助器方法:

导出函数匹配(
值:T,
检查:T[0],
检查2?:摘录[1]
) {
返回值[0]==check&(check2?值[1]==check2:true);
}
//另一个变体。。。
导出函数匹配(
值:T,
检查:T[0],
检查2:T扩展[推断X,推断Y]?提取[1]:从不
) {
返回值[0]==check&(check2?值[1]==check2:true);
}
它基本上是有效的——然而,我可以这样称呼它

匹配(状态为“空闲”、“探索”)
这对于编译器来说是可以的-我希望第二个参数的类型被解析为
从不
未定义

  • [“空闲”,“探索”]
    不可分配给
    状态
  • 写入
    提取
    正确提取
    从不
所以,我的问题是


为什么对“matches”的调用与表示无效类型的值成功匹配?Typescript不会根据在第二个参数中传递的值缩小
t
的类型

鉴于此代码:

type State = ["IDLE"] | ["STARTING_NEW_CONVERSATION"] | ["CHANNEL_ACTIVE", "SYNCED" | "EXPLORING"];
const state: State = {} as any

export function matches<T extends [string] | [string, string], X = T[0], Y = T[1]>(
  value: T,
  check: T[0],
  check2?: Extract<T, [X, Y]>[1]
) {
  return value[0] === check && (check2 ? value[1] === check2 : true);
}

matches(state, "IDLE", "EXPLORING")
当您将
“IDLE”
作为第二个参数传递时,TS只是查看它并说“是的,这与
“IDLE”|“STARTING_NEW_CONVERSATION”|“CHANNEL_ACTIVE”
匹配并继续。它不会缩小任何范围

如果需要基于彼此对第二个和第三个参数的类型强制执行约束,则应在模板参数列表中放置要约束的公共类型,并从两个参数中引用它:

value: State
check: "IDLE" | "STARTING_NEW_CONVERSATION" | "CHANNEL_ACTIVE"
check2: "SYNCED" | "EXPLORING"
function matches<T extends State, X extends T[0], Y extends T[1]>(
  value: T,
  check: X,
  check2?: Extract<T, [X, Y]>[1],
) {
  return value[0] === check && (check2 ? value[1] === check2 : true);
}

type State = ["IDLE"] | ["STARTING_NEW_CONVERSATION"] | ["CHANNEL_ACTIVE", "SYNCED" | "EXPLORING"];
const state: State = {} as any

matches(state, 'IDLE', ) // WORKS
matches(state, 'CHANNEL_ACTIVE', 'EXPLORING') // Works
matches(state, 'IDLE', 'EXPLORING') // ERROR: Argument of type '"EXPLORING"' is not assignable to parameter of type 'undefined'.
函数匹配(
值:T,
支票:X,
检查2?:提取[1],
) {
返回值[0]==check&(check2?值[1]==check2:true);
}
键入State=[“IDLE”]|[“STARTING_NEW_CONVERSATION”]|[“CHANNEL_ACTIVE”、“synched”|“EXPLORING”];
const state:state={}如有
匹配(状态为“空闲”)//有效
匹配(状态为“CHANNEL_ACTIVE”、“EXPLORING”)//有效
匹配(状态为“IDLE”、“EXPLORING”)//错误:“EXPLORING”类型的参数不可分配给“undefined”类型的参数。
关键区别在于,我们在模板列表中定义类型
X
,然后在两个参数约束中使用它。这迫使TS推断出满足两个参数的单个类型
X
。否则,参数的约束将不相关


(编辑:更新为与原始代码更接近的简化解决方案)

能否设置最小可复制示例?目前还不清楚,因为函数签名期望元组作为第一个参数,但传递字符串
匹配(“空闲”、“探索”)
完全没有对
状态的引用
类型。这是您问题中的输入错误吗?在操场上,此调用生成错误
“类型为'string'的参数不能分配给类型为'[string]|[string,string]'的参数。
True@ccarton-状态值是第一个参数hello@AlekseyL。-我添加了一个游乐场——运行它会因为一些我无法控制的原因而失败,但它表明一切都很好,即使从我的视角来看,它应该是非常酷和合理的——距离并不太远,基本上“检查”并没有受到足够的约束。