简体   繁体   English

通过在 Typescript 中添加类型断言来更改推理

[英]Change the inference by adding a type assertion in Typescript

From: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-inference来自: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-inference

TypeScript doesn't assume the assignment of 1 to a field which previously had 0 is an error. TypeScript 不假定将1分配给以前为0的字段是错误的。 Another way of saying this is that obj.counter must have the type number , not 0 , because types are used to determine both reading and writing behavior.另一种说法是obj.counter必须具有类型number ,而不是0 ,因为类型用于确定读取写入行为。

The same applies to strings:这同样适用于字符串:

 const req = { url: "https://example.com", method: "GET" }; handleRequest(req.url, req.method); // Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.

I thought "GET" is a default value assigned to variable 'method' of the object 'req'.我认为“GET”是分配给 object 'req' 的变量 'method' 的默认值。 What is the error saying?错误在说什么?

  1. You can change the inference by adding a type assertion in either location:您可以通过在任一位置添加类型断言来更改推理:

     // Change 1: const req = { url: "https://example.com", method: "GET" as "GET" }; // Change 2 handleRequest(req.url, req.method as "GET");

    Change 1 means “I intend for req.method to always have the literal type "GET" ”, preventing the possible assignment of "GUESS" to that field after.更改 1 的意思是“我打算让req.method始终具有文字类型"GET" ”,从而防止之后可能将"GUESS"分配给该字段。 Change 2 means “I know for other reasons that req.method has the value "GET" “.更改 2 的意思是“由于其他原因,我知道req.method的值为"GET" ”。

What do they mean by adding a type assertion in this case?在这种情况下添加类型断言是什么意思?

What is happening here?这里发生了什么?

If you hover over req , you'll see that method is a string.如果你 hover over req ,你会看到这个method是一个字符串。 The types have been "widened".类型已“扩大”。 You have to find a way to tell Typescript not to do that.你必须想办法告诉 Typescript 不要那样做。 One of these is using const .其中之一是使用const

const req = { url: "https://example.com", method: "GET" } as const;

Or you can explicitly say that method is either "GET" or "POST".或者您可以明确地说该method是“GET”或“POST”。

const req: { url: string, method: "GET" | "POST" } = { url: "https://example.com", method: "GET" as "GET" };

or using type assertion like you did as .或者像你一样使用类型断言as (We are often told not to use type assertions but that's a good use case) (我们经常被告知不要使用类型断言,但这是一个很好的用例)

This would work as well这也可以

const req = { url: "https://example.com", method: "GET" as const }; // const just on method

This little example will help you understand better what's happening:这个小例子将帮助您更好地理解正在发生的事情:

let num = 3 //number since you can assign something else to num
const num = 3 //3 since it's a const (not supposed to change)

When creating req , you're basically creating an object with an url: string and method: string .创建req时,您基本上是在使用url: stringmethod: string创建 object。 Here's an example equal to your code:这是一个与您的代码相同的示例:

interface Request {
  url: string;
  method: string;
}
const req: Request = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);

but this way, you can't ensure that method is GET or POST, so if handleRequest expects one of those values it will complain if you pass a "string", which could equal to anything.但这样一来,您无法确保该method是 GET 或 POST,因此如果 handleRequest 期望其中一个值,如果您传递一个“字符串”,它会报错,它可能等于任何值。

A solution could be to define a type for the req, for example:一个解决方案可能是为 req 定义一个类型,例如:

interface Request {
  url: string;
  method: 'GET' | 'POST';
}

// or using 'type' if you prefer
// type Request = {
//   url: string;
//   method: 'GET' | 'POST';
// }

const req: Request = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM