microsoft / microsoft/TypeScript

Generic type unnarrowed by `switch...case`

Đang mở
#43,873 10 bình luận 5 reaction 0 người được giao Xem trên GitHub

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

In Discussion Suggestion
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ả

Bug Report

🔎 Search Terms
  • narrowing of generic types
  • exhaustive switch case
🕗 Version & Regression Information

Theoretically this should be fixed by:

Similar issue:

I'm trying against the latest beta: 4.3.0-pr-43183-11 / 15fae38b39a370f1f597606e552dd40998a1ac49.

⏯ Playground Link

Playground link with relevant code

💻 Code
interface TopLevelElementMap {
	"a": HTMLElement;
	"b": HTMLElement;
}

interface ElementAttributes {}

interface ElementAttributesMap {
	"a": ElementAttributes;
	"b": ElementAttributes;
}

class Element<TagName extends keyof TopLevelElementMap> {
	protected attributes: ElementAttributesMap[TagName] = {};

	public constructor(type: TagName) {}
}

const ElementTagNameMap = {
	"a": function(): Element<"a"> {
		return new Element("a");
	},
	"b": function(): Element<"b"> {
		return new Element("b");
	}
};

function createPrimitive<TagName extends keyof typeof ElementTagNameMap>(tagName: TagName) {
	switch (tagName) {
		case "a":
			return function(): Element<TagName> {
				//
				// [?] Shouldn't `tagName` get narrowed to just "a"?
				//
				return ElementTagNameMap[tagName]();
			};

		case "b":

		default:
			throw new Error("Unrecognized element `" + tagName + "`.");
	}
}

const a = createPrimitive("a");
const b = createPrimitive("b");

As a workaround I can assert as Element<TagName> on the inner-most return statement to silence the error.

🙁 Actual behavior
Type 'Element<"a"> | Element<"b">' is not assignable to type 'Element<TagName>'.
  Type 'Element<"a">' is not assignable to type 'Element<TagName>'.
    Type '"a"' is not assignable to type 'TagName'.
      '"a"' is assignable to the constraint of type 'TagName', but 'TagName' could be instantiated with a different subtype of constraint '"a" | "b"'. (2322)
🙂 Expected behavior

TagName should be narrowed to one of the possible values dictated by the case clause.

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 bản tái hiện TypeScript Playground được liên kết và xác nhận lỗi đã báo cáo trên giá trị trả về generic bên trong case của switch. Truy vết quá trình narrowing kiểu generic của trình biên dịch cho các mệnh đề switch, sau đó thêm coverage hồi quy cho thấy case thu hẹp TagName và đoạn mã mong đợi được kiểm tra kiểu mà không cần assertion.

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
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
38/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.