Union Types 在使用变量时为什么不需要检查,但在函数内部却需要?

huangapple go评论64阅读模式
英文:

Why do we not need checks with Union Types when using a variable but it's needed inside a function?

问题

我正在做一些 TypeScript 的挑战,遇到了这个 union type 的示例。

我们说 getIstanbulPostalCode 返回一个 string 或一个 number

function getIstanbulPostalCode(): string | number {
  return 34116;
}
let postalCode: number = getIstanbulPostalCode();
postalCode;

结果:类型错误:类型 'string | number' 不能赋值给类型 'number'

变量 postalCode 引用了 getIstanbulPostalCode 并返回一个数字,与函数不匹配。

这个函数需要一个 string 或一个 number,所以它导致了一个 类型错误
类型 'string' 不能赋值给类型 'number'

对于函数 istanbul 的第二个示例,我感到困惑的地方在于,这个函数返回一个 number,这是有道理的。

但是为什么当我们创建 istanbul2,它可以是 stringnumber 时,我们不会得到任何类型错误呢?

我之所以提出这个问题,是因为在函数内部,如果你将一个 union type 作为参数提供,你必须检查它是一个 string 还是一个 number,否则会报错,但在这里,使用一个变量,我们可以无需检查地提供任何类型?

谢谢。

英文:

I'm doing some Typescript challenges and came across this union type example.

We are saying getIstanbulPostalCode returns a string or a number:

function getIstanbulPostalCode(): string | number {
  return 34116;
}
let postalCode: number = getIstanbulPostalCode();
postalCode;

Result: type error: Type 'string | number' is not assignable to type 'number'.

The variable postalCode references getIstanbulPostalCode and returns a number which doesn't match the function.

The function needs a string or a number so it results in a type error.
Type 'string' is not assignable to type 'number'.

function istanbul(): number { return 34116; }
let istanbul2: string | number = istanbul();
istanbul2;

Result: 34116

My confusion is in this second example for function istanbul, this function returns a number which makes sense.

But why is it when we create istanbul2 which can be either string or number we don't get any type errors?

I ask this because inside a function if you provide a union type as a parameter you have to check if it's a string or a number otherwise it complains, but here using a variable we can provide either with no checks?

Thanks

答案1

得分: 1

postalCode 变量期望一个数字类型的值,但 getIstanbulPostalCode 函数可以返回数字或字符串。鉴于 TypeScript 在编译时运行,而你告诉它函数可能返回数字或字符串中的任何一个,它会相信这一点,因此你会得到错误,因为它无法知道在运行时返回的是哪个联合类型中的哪一个。

如果你将函数重写如下,TypeScript 将推断它的返回类型为数字,不会抛出错误。

function getIstanbulPostalCode() {
  return 34116;
}
let postalCode: number = getIstanbulPostalCode(); // 没有错误
postalCode;

对于第二个情况,你说 istanbul2 可以是字符串或数字,而函数 istanbul 返回一个数字,这满足了它属于数字或字符串的约束,因此你不会看到任何错误。

英文:

The postalCode variable expects a value which is number, but function getIstanbulPostalCode can return either a number or a string. Given that typescript works at compile time, and you are telling it that the function return either number or string, it believes it and you get the error since it has no way of knowing which one of the two union type is returned at runtime.

If you were to rewrite your function as following, typescript will infer it's return type to be number and will not throw error.

function getIstanbulPostalCode() {
  return 34116;
}
let postalCode: number = getIstanbulPostalCode(); // no error
postalCode;

For your second case, you are saying that istanbul2 can be either a string or a number, and the function istanbul returns a number, which satisfies the constrain of it belonging to either number or string, and hence you do not see any errors.

答案2

得分: 0

> 但为什么当我们创建istanbul2时,它可以是字符串或数字,我们却没有得到任何类型错误?

嗯,你之所以没有得到任何错误,是因为数字是string | number的子类型。把管道看作或,你会得到(有效的)语句“数字是(字符串或数字)”,因此赋值是允许的。

然后,你只能使用这些类型的方法的交集。虽然console.log可以接受几乎任何东西,但你现在可以使用的方法(不需要检查)只有toLocaleString()toString()valueOf()(你甚至不能将+运算符与自身一起调用)。

在TS中,console.log被定义为接受any[]类型,所以它非常宽松。但如果你想对变量执行有用的操作,很可能需要在使用之前对其进行检查。

英文:

> But why is it when we create istanbul2 which can be either string or number we don't get any type errors?

Well, you do not get any errors because number is a subtype of string | number. Read the pipe as or and you get the (valid) statement "number is (string or number)" therefore the assignment is alllowed.

Using that variable, you are however restricted to the intersection of methods on these types.
While console.log will take pretty much anything, the only methods you can use now (without checking) are toLocaleString(), toString() and valueOf()
(You can not even call the + operator with itself)

console.log is typed in TS to take any[], so it is very generous. But if you wanted to to something useful with the variable, you likely need to check it before using.

huangapple
  • 本文由 发表于 2023年5月30日 02:23:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76359583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定