microsoft / microsoft/TypeScript

Error on function return is less useful than it should be

Đang mở
#63,357 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Domain: check: Contextual Types Possible Improvement
Ngôn ngữ chính
Go
Star
111k
Fork
14.3k
Merge trung bình
2 ngày 4 giờ
Pull request đã merge (30 ngày)
132

Mô tả

### 🔍 Search Terms

"contextual typing of function return values" "function return error in the wrong place"

### ✅ Viability Checklist

- [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- [x] This wouldn't change the runtime behavior of existing JavaScript code
- [x] This could be implemented without emitting different JS based on the types of the expressions
- [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- [x] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- [x] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

### ⭐ Suggestion

Often when writing a function where the return type should be known, errors appear overly complicated and far away from their source.

```ts
type Ret = {a: number};
type Fn = () => Ret;

const issue: Fn = () => {
// ^ it shows the error here: Type '() => { a: string; }' is not assignable to type '() => { a: number; }'.
return {a: "25"};
// ^ instead of here
};

// adding an explicit return type fixes it
const workaround1: Fn = (): Ret => {
return {a: "25"};
// ^ shows here: Type 'string' is not assignable to type 'number'.
};

// returning without a block body fixes it
const workaround2: Fn = () => ({a: "25"});
// ^ shows here: Type 'string' is not assignable to type 'number'.

// using a helper function fixes it
function inferRet(arg: NoInfer): T {
return arg;
}
const workaround3: Fn = () => {
return inferRet({a: "25"});
// ^ shows here: Type 'string' is not assignable to type 'number'.
};
```

Unfortunately, this would be a breaking change as it would cause some existing working code to now error, so it would have to be added under a compiler flag or wait for 7.0/8.0:

```ts
const breaking: Fn = () => {
return {a: 25, b: 56};
// ^ previously, there would be no error here.
// with this change: Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
};
```

[Playground link](https://www.typescriptlang.org/play/?ts=6.0.2#code/C4TwDgpgBAShxQLxQN4EMBcUB2BXAtgEYQBOAvgNwBQokUAYtklABQCUSAfLPNVQMYB7bAGcEASxEjcELI2bsuqKgHoVUDVAB6UcQhEALQQHcRUYAeikSgklEslZUACrhoAckWJuKKJihiJOLYAOYUUGTuumbYgghoUuIh2GiEADbQwILmblCeHN6oflh4RKThkQB0VJpQjsC4JEzoWABEAEwArK2Uquq1AzrBYhBoACZQggBm9qQQVL19fmNjwSF+TBAAHmBp4vx6dfCNTLTQU+JbEGZ6AsJiUMa2ANZoNrjYYwCMckzI7Fg4AhCigapp6idUP4Ot1emoBoMAkZTLNHFhXHR3IE1lFJDg4n5EslUhlzNkznlSsQSO5qot4RCmmtHnojLh4lB0oJ+M9OYIxiAoBcrjdgHdRAgniRXu9Pu1fgoCtwWC0oDCemxqPCETrdbqdIYTGYHE4MR5saFcTECQkREkUulMuTcu4qaRaVRxQ9CI40M81gr-krlLVGc1-F0ADScrCdABscP6eoROjAjgAbuJBLgRGkQNGLHNHtm0hNiPioNZbKiINVtcmdcZWeYDHj+AY0KEnAB5QgAKwg-AQe2ApDQaSg+DQguEeYCkAOU0Fz1ixiYacEkBIwHE12jnYm7kIUTGgmu+IQ20kElOLt8-jdJAqHsoQA)

### 📃 Motivating Example

```ts
interface App {
start: () => {
title: {
name: string,
},
},
}

export const app: App = {
start: () => {
return {
title: {
name: 25,
},
};
},
};
```

[Playground link](https://www.typescriptlang.org/play/?ts=6.0.2#code/JYOwLgpgTgZghgYwgAgIIAd3IN4ChkHIDOYcUYAXMgBQCUyAvAHw76HtjBgA2EVe7QYRBwAtn2JgooAOYAaNkIC+C9itxLcuCAA90Ae3LIE+kCWRxMVDFgat2JMpRr1m9ocigQwAVygh3D0JOHgkBII8RcSoAJgBWVQiCdSClAG5FZHV0oA)

Previously, the error would show as:

```
10 | start: () => {
~~~~~
Type '() => { title: { name: number; }; }' is not assignable to type '() => { title: { name: string; }; }'.
Call signature return types '{ title: { name: number; }; }' and '{ title: { name: string; }; }' are incompatible.
The types of 'title.name' are incompatible between these types.
Type 'number' is not assignable to type 'string'.(2322)
input.tsx(2, 5): The expected type comes from property 'start' which is declared here on type 'App'
```

With this change, the error will show as:

```
13 | name: 25,
~~~~
Type 'number' is not assignable to type 'string'.(2322)
input.tsx(2, 5): The expected type comes from property 'name' which is declared here on type '{ name: string; }'
```

The second one is clearly easier to read and fix

### 💻 Use Cases

1. What do you want to use this for?
Interfaces that define functions with return types
2. What shortcomings exist with current approaches?
workaround 1: Explicitly setting the return type is annoying, and shouldn't need to be done when typescript clearly knows what it should be.
workaround 2: Not using a block body is often not reasonable when computation needs to be done in the body of the function.
workaround 3: You shouldn't need to define a helper function for this
3. What workarounds are you using in the meantime?
Every time I define a function where the return type could be inferred, I always specify it manually to make the errors easier to read.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với hai ví dụ Playground để tái hiện các chẩn đoán hiện tại và so sánh các vị trí cùng thông báo được báo cáo. Điều tra cách các kiểu trả về theo ngữ cảnh được xử lý đối với các hàm có thân dạng khối, sau đó xác minh rằng các lỗi được chuyển đến biểu thức trả về gây ra lỗi mà không thay đổi hành vi đã được ghi lại đối với thuộc tính dư thừa.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
typescript
Lĩnh vực
compilers
Loại issue
Tính năng
Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
45/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.