A.S.: The question is not about "Why is there an error?", but rather about "Why does the error go away if I barely change it?".

我有一个相对简单的逻辑来为正则表达式验证器函数创建参数,该函数从sourceflags个字符串输入的组合中收集正则表达式,或者直接从正则表达式输入中收集正则表达式;在这两种情况下,它都需要验证配置.有些输入是可选的,有些是必需的.

它看起来是这样的:

type Options = { foo: 'bar' }

type ArgsRegExp = [first: RegExp, second?: Options]
type ArgsString = [first: string, second?: string, third?: Options]
type Args = ArgsRegExp | ArgsString

interface Params {
  readonly pattern: RegExp
  readonly options?: Options
}

function getParams(args: ArgsRegExp): Params
function getParams(args: ArgsString): Params
function getParams([first, second, third]: Args): Params {
  if (first instanceof RegExp) {
    return {
      pattern: first,
      options: second,
//             ^^^^^^ Error!
    }
  }

  return {
    pattern: new RegExp( // weird new lines are explained in the playground 
      first,
      second
//    ^^^^^^ Error!
    ),
    options: third,
  }
}

100.

这里有一个错误:second arg总是string | Options | undefined,因此在两种情况下都不能赋值(在第一种情况下必须是Options | undefined,在第二种情况下必须是string | undefined).

This error is expected,而且(如果我理解正确的话)与https://github.com/microsoft/TypeScript/issues/30581有关

然而,not所期望的是,一段非常相似的代码(这里有the diff view段)可以很好地工作,而不会产生任何可分配性问题,因为它完美地缩小了您希望的项目:

type Common = 'c'

type ArgsRegExp = [first: 'a0', second?: Common]
type ArgsString = [first: 'b0', second?: 'b1', third?: Common]
type Args = ArgsRegExp | ArgsString

interface Params {
  readonly custom: string
  readonly common?: Common
}

function getParams(args: ArgsRegExp): Params
function getParams(args: ArgsString): Params
function getParams([first, second, third]: Args): Params {
  if (first === 'a0') {
    return {
      custom: first,
      common: second,
//            ~~~~~~ No error?
    }
  }

  return {
    custom: // weird new lines are explained in the playground
      first +
      second,
//    ~~~~~~ No error?
    common: third,
  }
}

100.

这是怎么回事?Why does this work, but the original example doesn't?我知道类型不同,但我不能准确指出是哪种差异导致了两个例子的行为不同.

推荐答案

type Options = { foo: 'bar' }
type ArgsRegExp = [first: RegExp, second?: Options]
type ArgsString = [first: string, second?: string, third?: Options]
type Args = ArgsRegExp | ArgsString

Args型是notadiscriminated union型.TypeScrip中的区分联合要求其区分属性为literal types或包括literal types.您正在打开第一个元组元素,它要么是RegExp,要么是string,这两个元素都不是文字类型.因此,该元素不会被视为判别式,因此在判断该元素时不会进行缩小.

另一方面,在

type Common = 'c'   
type ArgsRegExp = [first: 'a0', second?: Common]
type ArgsString = [first: 'b0', second?: 'b1', third?: Common]
type Args = ArgsRegExp | ArgsString

您的第一个元素是类型"a0""b0",这两个类型都是文字类型.这是一个有区别的并集,你可以判断第一个元素,得到你想要的缩小范围.

Typescript相关问答推荐

如何根据参数的值缩小函数内的签名范围?

类型脚本如何将嵌套的通用类型展开为父通用类型

如何在TypeScript对象迭代中根据键推断值类型?

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

在使用Typescribe时,是否有一种方法可以推断映射类型的键?

如何将类型从变量参数转换为返回中的不同形状?

React重定向参数

如何在TypeScrip中从字符串联合类型中省略%1值

STypescript 件的标引签名与功能签名的区别

Angular 15使用react 式表单在数组内部创建动态表单数组

记录键的泛型类型

如何在方法中正确地传递来自TypeScrip对象的字段子集?

(TypeScript)TypeError:无法读取未定义的属性(正在读取映射)"

如何将对象数组中的键映射到另一种对象类型的键?

在正常函数内部调用异步函数

作为参数的KeyOf变量的类型

来自枚举的<;复选框和组件列表

通过辅助函数获取嵌套属性时保留类型

将带有额外id属性的Rust struct 展平回TypeScript单个对象,以返回wasm-bindgen函数

必须从注入上下文调用Angular ResolveFn-inject()