Javascript 字符串与字符串文字不兼容

Javascript 字符串与字符串文字不兼容,javascript,flowtype,Javascript,Flowtype,我从这个代码片段中得到了流错误 type MyType = 'aa' | 'bb' const str = 'a' const test1: MyType = `a${str}` // ERROR const test2: MyType = 'a' + str // ERROR 错误 链接: 有人知道为什么flow不支持这个吗?或者,有没有更好的方法来编写此代码以使流更愉快?谢谢 Flow是Javascript的静态类型检查器。这意味着flow只以静态方式分析源代码 在您的示例中,test1

我从这个代码片段中得到了流错误

type MyType = 'aa' | 'bb'

const str = 'a'
const test1: MyType = `a${str}` // ERROR
const test2: MyType = 'a' + str // ERROR
错误

链接:


有人知道为什么flow不支持这个吗?或者,有没有更好的方法来编写此代码以使流更愉快?谢谢

Flow是Javascript的静态类型检查器。这意味着flow只以静态方式分析源代码

在您的示例中,
test1
test2
变量在运行时都将变为等于
aa
,这等于
MyType
的两个授权值之一

不幸的是,这是运行时的结果。流仅检查静态规则。就我所见,Flow从不执行它检查的代码(即使代码像您的示例中那样微不足道)。

归因于

简短回答:不要写

长答覆:

以下是我想要此功能的原因:

// =====================
// Icon component
// =====================
// ICONS contains all the svg icons in the app
// I use prefix like FRUIT_ to differentiate the categories
const ICONS = {
  FRUIT_APPLE: <svg>...</svg>,
  FRUIT_ORANGE: <svg>...</svg>,
  VEGE_BROCCOLI: <svg>...</svg>,
  VEGE_TOMATO: <svg>...</svg>,
  ...
}

const Props = {
  type: $Keys<typeof ICONS>
}

const Icon = ({ type }: Props): Element<*> => (
  <i className={`Icon Icon--{type}`} />  
)

// =====================
// FruitCard component
// =====================
type Props = {
  fruitType: 'APPLE' | 'ORANGE',
  foo: string,
  ...
}

const FruitCard = (props: Props) => (
  <div>
     <div>{props.foo}</div>
     {/* Flow ERROR below */}
     <Icon type={`FRUIT_${props.fruitType}`} />
  </div>
) 
//=====================
//图标组件
// =====================
//图标包含应用程序中的所有svg图标
//我使用前缀像水果来区分类别
常量图标={
水果和苹果:。。。,
水果橙:。。。,
蔬菜花椰菜:。。。,
蔬菜番茄:。。。,
...
}
常量道具={
类型:$Keys
}
常量图标=({type}:Props):元素=>(
)
// =====================
//水果卡组件
// =====================
类型道具={
果实类型:“苹果”|“橙色”,
傅:字符串,
...
}
常量水果卡=(道具:道具)=>(
{props.foo}
{/*下面的流错误*/}
) 
解决方案1:使用对象将水果类型转换为图标类型 这就是我正在使用的解决方案

// =====================
// FruitCard component
// =====================
type Props = {
  fruitType: 'APPLE' | 'ORANGE',
  foo: string,
  ...
}

// Use object to convert fruitType to icon type
const FRUIT_TYPE_TO_ICON_TYPE = {
  APPLE: 'FRUIT_APPLE',
  ORANGE: 'FRUIT_ORANGE',
}

const FruitCard = (props: Props) => (
  <div>
     <div>{props.foo}</div>
     {/* This works in flow */}
     <Icon type={FRUIT_TYPE_TO_ICON_TYPE[props.fruitType]} />
  </div>
) 
//=====================
//水果卡组件
// =====================
类型道具={
果实类型:“苹果”|“橙色”,
傅:字符串,
...
}
//使用对象将水果类型转换为图标类型
常量水果类型到图标类型={
苹果:“水果苹果”,
橙色:“水果橙”,
}
常量水果卡=(道具:道具)=>(
{props.foo}
{/*这在流中工作*/}
) 
解决方案2:使用$ObjMap,将层次结构嵌入到类型系统中 这是由于。我认为这是一个更好的解决方案,因为它不需要对象映射

import React, {type Element} from "react";

// Type definitions. (There are other ways to structure these; this is
// relatively simple and works fine.)
type IconCategories = {
  FRUIT: FruitTypes,
  VEGE: VegeTypes,
};
type FruitTypes = {
  APPLE: "APPLE",
  ORANGE: "ORANGE",
};
type VegeTypes = {
  BROCCOLI: "BROCCOLI",
  TOMATO: "TOMATO",
};

// ICONS contains all the SVG icons in the app.
// Each category has its own nested object.
// This will fail to typecheck if you forget to include a category, or
// include an extra category, or forget to include a fruit/vegetable, or
// include an extra fruit/vegetable, or if any of the leaves is not an
// <svg /> element.
const ICONS: $Exact<$ObjMap<IconCategories, <T>(T) =>
  $Exact<$ObjMap<T, <U>(U) => Element<"svg">>>
>> = {
  FRUIT: {
    APPLE: <svg />,
    ORANGE: <svg />,
  },
  VEGE: {
    BROCCOLI: <svg />,
    TOMATO: <svg />,
  },
};

// Icon component
// Example usage: <Icon category="FRUIT" type="APPLE" />.
const Icon = <T: $Keys<IconCategories>>(props: {
  category: T,
  type: $Keys<$ElementType<IconCategories, T>>,
}) => (
  <i className={`Icon Icon--${props.category}_${props.type}`} />
);

// The following typecheck (which is good):
<Icon category="FRUIT" type="APPLE" />;
<Icon category="VEGE" type="BROCCOLI" />;

// The following do not typecheck (which is good):
/*
<Icon category="FRUIT" type="BROCCOLI" />;
<Icon category="VEGE" type="APPLE" />;
<Icon category="NOT_A_CATEGORY" type="WAT" />;
<Icon category="FRUIT" type="NOT_A_FRUIT" />;
*/

// FruitCard component
type Props = {
  fruitType: "APPLE" | "ORANGE",  // or: `fruitType: $Keys<FruitTypes>`
  foo: string,
};

const FruitCard = (props: Props) => (
  <div>
    <div>{props.foo}</div>
    {/* This typechecks, correctly */}
    <Icon category="FRUIT" type={props.fruitType} />
  </div>
);
import React,{type Element}来自“React”;
//类型定义。(还有其他方法来构建这些结构;这是
//相对简单,效果很好。)
类型图标类别={
水果:水果类型,
VEGE:VegeTypes,
};
类型水果类型={
苹果:“苹果”,
橙色:“橙色”,
};
类型VegeTypes={
西兰花:“西兰花”,
西红柿:“西红柿”,
};
//图标包含应用程序中的所有SVG图标。
//每个类别都有自己的嵌套对象。
//如果您忘记包含类别,则无法进行类型检查,或者
//包括额外的类别,或忘记包括水果/蔬菜,或
//包括额外的水果/蔬菜,或者如果任何叶子不是
//元素。
常量图标:$Exact
>> = {
水果:{
苹果:,
橙色:,
},
蔬菜:{
西兰花:,
番茄:,
},
};
//图标组件
//用法示例:。
常量图标=(道具:{
类别:T,
类型:$Keys,
}) => (
);
//以下类型检查(这很好):
;
;
//以下内容不进行打字检查(这很好):
/*
;
;
;
;
*/
//水果卡组件
类型道具={
果型:“苹果”|“橙色”//or:`果型:$key`
傅:字符串,
};
常量水果卡=(道具:道具)=>(
{props.foo}
{/*此类型检查是否正确*/}
);
下面是关于github的更深入的讨论:

谢谢!这是有道理的。当复制和粘贴别人的答案时,礼貌的做法是给他们(即我)正确的归因。@wchargin添加了你的归因。让我知道这是否是添加属性的正确方法。对不起,我是stackoverflow的新手。:)
import React, {type Element} from "react";

// Type definitions. (There are other ways to structure these; this is
// relatively simple and works fine.)
type IconCategories = {
  FRUIT: FruitTypes,
  VEGE: VegeTypes,
};
type FruitTypes = {
  APPLE: "APPLE",
  ORANGE: "ORANGE",
};
type VegeTypes = {
  BROCCOLI: "BROCCOLI",
  TOMATO: "TOMATO",
};

// ICONS contains all the SVG icons in the app.
// Each category has its own nested object.
// This will fail to typecheck if you forget to include a category, or
// include an extra category, or forget to include a fruit/vegetable, or
// include an extra fruit/vegetable, or if any of the leaves is not an
// <svg /> element.
const ICONS: $Exact<$ObjMap<IconCategories, <T>(T) =>
  $Exact<$ObjMap<T, <U>(U) => Element<"svg">>>
>> = {
  FRUIT: {
    APPLE: <svg />,
    ORANGE: <svg />,
  },
  VEGE: {
    BROCCOLI: <svg />,
    TOMATO: <svg />,
  },
};

// Icon component
// Example usage: <Icon category="FRUIT" type="APPLE" />.
const Icon = <T: $Keys<IconCategories>>(props: {
  category: T,
  type: $Keys<$ElementType<IconCategories, T>>,
}) => (
  <i className={`Icon Icon--${props.category}_${props.type}`} />
);

// The following typecheck (which is good):
<Icon category="FRUIT" type="APPLE" />;
<Icon category="VEGE" type="BROCCOLI" />;

// The following do not typecheck (which is good):
/*
<Icon category="FRUIT" type="BROCCOLI" />;
<Icon category="VEGE" type="APPLE" />;
<Icon category="NOT_A_CATEGORY" type="WAT" />;
<Icon category="FRUIT" type="NOT_A_FRUIT" />;
*/

// FruitCard component
type Props = {
  fruitType: "APPLE" | "ORANGE",  // or: `fruitType: $Keys<FruitTypes>`
  foo: string,
};

const FruitCard = (props: Props) => (
  <div>
    <div>{props.foo}</div>
    {/* This typechecks, correctly */}
    <Icon category="FRUIT" type={props.fruitType} />
  </div>
);