Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TypeScript接口能否要求多个字符串键或值相同?_Typescript - Fatal编程技术网

TypeScript接口能否要求多个字符串键或值相同?

TypeScript接口能否要求多个字符串键或值相同?,typescript,Typescript,假设我想创建一个界面,看起来像这样: 接口调色板{ defaultColorName:字符串//应以以下颜色存在 颜色:{ [颜色名称:字符串]:字符串//将颜色名称与颜色关联(十六进制字符串) } } 换句话说,此调色板概念允许指定颜色列表(每个颜色都可以通过任意颜色名称访问),但也可以提供默认颜色 我想知道在TypeScript中是否可以强制键/值对象defaultColorName中存在defaultColorName的值,因为指定colors中不存在的默认颜色是没有意义的 我知道如果颜

假设我想创建一个
界面
,看起来像这样:

接口调色板{
defaultColorName:字符串//应以以下颜色存在
颜色:{
[颜色名称:字符串]:字符串//将颜色名称与颜色关联(十六进制字符串)
}
}
换句话说,此调色板概念允许指定颜色列表(每个颜色都可以通过任意颜色名称访问),但也可以提供默认颜色

我想知道在TypeScript中是否可以强制键/值对象
defaultColorName
中存在
defaultColorName
的值,因为指定
colors
中不存在的默认颜色是没有意义的

我知道如果颜色名称是一个字符串联合,例如
type ColorType='bright'|'dark'|'minute'
,我可以在
接口中使用泛型,例如
接口colorplate
。在本例中,颜色名称是任意的
string
s,可以是任何颜色


我使用调色板的概念来演示我想要做的事情,我的实际用例并不特定于颜色。

这里的关键因素是:

在本例中,颜色名称是任意字符串,可以是任何内容


由于这一规定,您所要求的是不可能的,因为您要求TypeScript编译器(令人惊讶的是,它只存在于编译时)根据运行时发生的事情做出决定(将任意字符串键/值对插入
颜色
对象).

Typescript typesafety仅在编译时使用。因此,编译器无法验证在编译时未知的任何内容


此外,如果没有显式的运行时检查,您甚至不能保证在编译时完全有效的所有假设在运行时仍然有效。想象一下,您正在从一个文件或API读取JSON数据,并期望该数据遵循某个接口。但是如果没有显式的运行时检查,可能会出现各种运行时错误或意外/未定义的行为。例如,属性可能丢失或类型错误。

您当然可以在TypeScript中描述您正在讨论的约束,但不能作为特定类型。相反,您可以将泛型(如您所提到的)与助手函数一起使用,以便可以推断泛型类型参数,而不是手动指定

虽然TypeScript的类型系统确实在运行时不存在,但类型系统的思想是描述在运行时确实存在的值集。指出你事先不知道颜色名称是什么,这有点像转移视线。有一种实用程序类型,它的巨大实用性并没有因为我现在无法告诉您哪些特定键将位于
K
中而降低

强烈键入
colorplate
来表示约束可能有用,也可能不有用,这取决于是否值得在TypeScript代码周围拖动泛型类型参数。但这不同于说它没有用,因为类型系统被擦除了


例如:

interface ColorPalette<K extends string> {
  colors: {
    [P in K]: string // associate a color name to a color (hex string)
  };
  defaultColorName: NoInfer<K> // should exist in colors above
}

type NoInfer<T> = [T][T extends any ? 0 : never]; // see microsoft/TypeScript#14829    

const asColorPalette = <K extends string>(
  colorPalette: ColorPalette<K>) => colorPalette;
function useColorPalette<K extends string>(colorPalette: ColorPalette<K>) {
  for (let k in colorPalette.colors) {
    console.log(k + "->" + colorPalette.colors[k].toUpperCase());
  }
  console.log(
    "The hex string corresponding to the default color is " +
    colorPalette.colors[colorPalette.defaultColorName].toUpperCase()
  );
 colorPalette.colors.aquamarine; // error!
 // Property 'aquamarine' does not exist on type '{ [P in K]: string; }'
}
在这里,编译器接受
okaycolorplate
differentcolorplate
,但拒绝
badcolorplate
。因此,如果编写任何指定颜色名称的TypeScript代码,编译器将帮助您


即使您从未在TypeScript代码中实际看到具体的颜色名称,
ColorPalette
类型仍然可以使用。大概您想编写一些TypeScript代码来操纵一些未知的
K
colorplate
值,对吗?例如:

interface ColorPalette<K extends string> {
  colors: {
    [P in K]: string // associate a color name to a color (hex string)
  };
  defaultColorName: NoInfer<K> // should exist in colors above
}

type NoInfer<T> = [T][T extends any ? 0 : never]; // see microsoft/TypeScript#14829    

const asColorPalette = <K extends string>(
  colorPalette: ColorPalette<K>) => colorPalette;
function useColorPalette<K extends string>(colorPalette: ColorPalette<K>) {
  for (let k in colorPalette.colors) {
    console.log(k + "->" + colorPalette.colors[k].toUpperCase());
  }
  console.log(
    "The hex string corresponding to the default color is " +
    colorPalette.colors[colorPalette.defaultColorName].toUpperCase()
  );
 colorPalette.colors.aquamarine; // error!
 // Property 'aquamarine' does not exist on type '{ [P in K]: string; }'
}
函数useColorPalette(colorPalette:colorPalette){
for(让k在colorplate.colors中){
console.log(k+“->”+colorplate.colors[k].toUpperCase());
}
console.log(
“与默认颜色对应的十六进制字符串为”+
colorPalette.colors[colorPalette.defaultColorName].toUpperCase()
);
colorPalette.colors.aquamarine;//错误!
//属性“aquamarine”在类型“{[P in K]:string;}”上不存在
}
由于泛型类型,编译器对
colorplate
有一点了解:它知道
for..in
循环生成一个
k
,可用于索引到
colors
属性中;它知道
defaultColorName
属性可以用作
colors
属性的键;它知道一些随机字符串,比如
“aquamarine”
,不一定可以用作
colors
属性的键。如果您只是使用
string
而不是
K extends string
,编译器将允许使用
aquamarine
索引


再说一次,这对你来说可能不值得。泛型类型比特定类型更难处理。但这并不像“别麻烦了,因为TypeScript在你运行任何东西之前就消失了”


如果在编译时不知道它们,不,您不能怀疑是这种情况,谢谢您的解释和确认!