【问题标题】:Why flow type casting not working for string literal as expected为什么流类型转换不能按预期对字符串文字起作用
【发布时间】:2022-11-07 14:47:11
【问题描述】:

对于下面的示例,为什么类型转换在 Flowtypes 中不起作用?理想的做法应该是什么?

type typeA = {
  name: 'ben' | 'ken',
};
type typeB = {
  name: string,
};
const objA: typeA = { name: 'ben' };
const objB: typeB = objA;

它给出了错误

Cannot assign `objA` to `objB` because in property `name`: Either  string [1] is incompatible with  string literal `ben` [2]. Or  string [1] is incompatible with  string literal `ken` [3].

但是,对于打字稿来说,这很好。

【问题讨论】:

    标签: javascript flowtype


    【解决方案1】:

    这实际上是 IMO 的 TypeScript 缺陷,Flow 做得对。让我们看看为什么:

    type A = {
      name: 'ben' | 'ken';
    }
    
    type B = {
      name: string;
    }
    
    const a: A = { name: 'ben' }
    const b: B = a;
    
    b.name = 'jen';
    
    console.log({ a });
    // this logs { a: { name: 'jen' } } <- see how a.name has an invalid value!
    

    在 JS 中,当您编写 b = a 时,意味着 ba 的“别名”,实际上它们是同一个对象。

    因此,如果您对b 进行更改,那么这些更改也会反映在a 上,因此如果您被允许将name 类型定义从给定的字符串列表“倾斜”为通用字符串,您可以去将a.name 更改为“非法”或更好的不需要的值!

    【讨论】:

      【解决方案2】:

      让我们检查一下为什么您的代码不安全,Flow Try

      type typeA = {
        name: 'ben' | 'ken',
      };
      type typeB = {
        name: string,
      };
      const objA: typeA = { name: 'ben' };
      const objB: typeB = objA // correctly catches error here because...
      
      const mutateTypeB = (val: typeB): void => {
         val.name = "len"; // ...no error is caught here
      }
      
      mutateTypeB(objB);
      // now objA.name = "len"  
      

      您的错误可以通过两种方式解决:

      1. typeB Flow Try 中将名称命名为ReadOnly 字段
        type typeA = {
          name: 'ben' | 'ken',
        };
        type typeB = {
          +name: string,
        };
        const objA: typeA = { name: 'ben' };
        const objB: typeB = objA;
        
        const mutateTypeB = (val: typeB): void => {
           val.name = "len"; // error caught here instead
        }
        
        mutateTypeB(objB);
        // now objA.name = "len"   
        
        1. typeA Flow Try 中添加string 作为联合的一部分
        type typeA = {
          name: 'ben' | 'ken' | string,
        };
        type typeB = {
          name: string,
        };
        const objA: typeA = { name: 'ben' };
        const objB: typeB = objA;
        

        你可以阅读更多关于这个确切问题here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-30
        • 1970-01-01
        相关资源
        最近更新 更多