【问题标题】:Why does this type guard not work on generic parameters?为什么这种类型保护不适用于泛型参数?
【发布时间】:2021-03-21 14:35:18
【问题描述】:

考虑以下代码 (TS Playground):

function identity<T>(value: T): T {
  if (typeof value === 'string') {
    return value.replace('foo', 'bar'); // <-- ERROR
  }
  return value;
}

导致错误Type 'string' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.

似乎类型保护不足以缩小泛型参数的类型并执行字符串操作。

为什么会出现这个错误,我该如何解决?

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    假设函数被这样调用

    const example: 'foo' = 'foo';
    
    const result = identity(example);
    

    根据函数的类型定义,由于T"foo"(即一个特定的字符串,而不是一般的string),所以我也必须返回一个"foo"。但是函数内部的代码会返回“bar”,所以它违反了类型。


    为了做你想做的事,你需要使用函数重载来为字符串情况提供与其他情况不同的类型。例如:

    function identity<T>(value: string): string;
    function identity<T>(value: T): T;
    function identity<T>(value: T): T | string {
      if (typeof value === 'string') {
        return value.replace('foo', 'bar');
      }
      return value;
    }
    

    如果使用T == "foo" 调用此代码,则打字稿将看到"foo" 的值是compatiblevalue: string,因此函数的第一个类型定义匹配。根据该类型定义,返回值因此是一般的string

    Playground link

    【讨论】:

    • 谢谢,这是有道理的。有没有办法重写这个函数,我可以替换字符串中的文本,但以类型安全的方式保留其他所有内容?
    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多