给出以下示例:
interface Data {
name: string;
value: number;
}
const data :Data = {
name: 'name',
value: 1,
}
const updateValue = (key: keyof Data, value: string | number): void => {
data[key] = value;
};
打字稿显示以下错误:
Type 'string | number' is not assignable to type 'string & number'.
Type 'string' is not assignable to type 'string & number'.
Type 'string' is not assignable to type 'number'.
这是清楚易懂的。但是,如果我像这样向接口添加联合类型:
type MultiType = 'x' | 'y';
interface Data {
name: string;
value: number;
multiType: MultiType | null;
}
const data :Data = {
name: 'name',
value: 1,
multiType: null,
}
const updateValue = (key: keyof Data, value: string | number): void => {
data[key] = value;
};
我收到以下错误:
Type 'string | number' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.
如果我使用交集类型string & number & MultiType
,Typescript会接受它,但也接受never
。
这似乎与我不一致。这可能是错误吗?
答案 0 :(得分:3)
string & number
等效于never
,string & number & (MultiType | null)
也等效。没有同时为string
和number
的值,因此没有值满足string & number
或string & number & AnythingElse
。
现在后面的explicitly reduces to never
是因为它包含这些等效于never
类型的并集,这样离开真是很难看。具体来说,编译器将交集分布在并集上,因此
string & number & ('x' | 'y' | null)
成为
(string & number & 'x') | (string & number & 'y') | (string & number & null)
该类型对人们的启发并不特别,因此编译器会检查每个联合组成部分是否等同于never
并将该类型简化为
never | never | never
这只是
never
如您所见。
那么为什么string & number
本身不会立即减少为never
?最初的想法很不错,因为string is not assignable to number
比string is not assignable to never
更具启发性,它可以帮助人们理解代码中的错误来源。
不幸的是,就可为其赋值和从中赋值而言,string & number
与never
等价于string | number is not assignable to never
,但是在TS3.5及以下版本中,编译器并不总是处理它们相同,这令人困惑。
因此,从TS3.6开始,empty intersections like string & number
will be reduced to never
explicitly看起来像。 TS3.6发布后,您的上述代码在两种情况下都将发挥相同的作用,并且会出现 from helpers.helper_a import *
import pandas as pd
query_train_data = "select * from train;"
df_train_dataset = pd.read_sql(query_train_data, con=engDps1000)
query_test_data = "select * from test;"
df_test_dataset = pd.read_sql(query_test_data, con=engDps1000)
df_train_data = df_train_dataset
df_test_data = df_test_dataset
data_prep_steps() # This function is defined in helpers_a
Error:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-12-3c88b46f341a> in <module>
----> 1 data_prep_steps()
~\Desktop\Notebooks\helpers\helper_a.py in data_prep_steps()
---> 89 # STEP 1 : CONVERT REQUIRED COLS TO CATEGORIES
90 for df_name in [df_train_data, df_test_data]:
91 data_prep_class = data_prep(df_name)
错误。
好的,希望能有所帮助;祝你好运!
答案 1 :(得分:1)
两件事:
由于以下所有原因,TypeScript不接受string | number
作为value
参数的类型是合乎逻辑的:
string | number
无法分配给string
,因为在number
为string
的情况下key
无法分配给'name'
< / p>
string | number
无法分配给number
,因为在string
为number
的情况下key
无法分配给'value'
(在您的第一个示例中,两个都已经成立了
string | number
无法分配给MultiType | null
,因为在number
的情况下string
和'x' | 'y' | null
都不能分配给key
是'multiType'
但是,由于某些原因,在第一个示例中,TypeScript只是在第一个“错误”情况下停止并给出了此错误(即使实际上已经有两件事出了错)。
在第二种情况下,您可能会看到相同的错误消息,因为类型的不兼容性仍然存在,推断似乎更加深入,并告诉您问题比这更深。至于为什么错误消息是这样格式化的,我真的不知道,我想这将需要更深入地了解编译器在此处的推断方式。最后,编译器是正确的,但错误消息可能会更清楚。
对于第二个问题,the never
type文档说:
never
类型是每种类型的子类型,并且可以分配给每种类型
所以这就是为什么您可以将value
指定为never
类型并将其分配给data
的原因。因为它将永远不会发生。