microsoft / microsoft/TypeScript

Confusing enum reverse string lookup behaviour in strict mode

Đang mở
#29,094 6 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: Error Messages Experience Enhancement 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ả

Summary

Code below.

Typescript in --strict mode will reject enum reverse lookups using arbitrary strings with this very confusing error message:

Element implicitly has an 'any' type because index expression is not of type 'number'.

A workaround is to cast the string to a subset of all possible enum keys but that's impractical with large enums (or is there an easy way to say "any key of enum X" in TS?).

My real world use case: I have a react app with a <select> filter on various items, and a bunch of <option> values, all of which are part of an integer enum. I have to use the string representation in the dom, so the state of the filter has to be the string representation. When I check the item's enum value I already know it can only be one of those enum members.

This report is three-fold:

  1. Is this behaviour intended? There are cases where it can definitely catch a reverse lookup that can fail.
  2. If it is intended, then what is the correct way to declare that the lookup will always be valid? let typeFilter: "FOO" | "BAR" = "FOO" is impractical and increases risk of errors.
  3. Regardless of the above, the error message should be fixed. The element highlighted (typeFilter) does not in fact have an "any" type, and Type[typeFilter] will not be any either (in fact, Type[typeFilter] as Type does not fix it). An error such as "Reverse lookup on enum Type may fail because typeFilter is of type 'string'" is much clearer already.

Details

TypeScript Version: 3.2.2

Search Terms: enum reverse string lookup

Code

// test.ts
// Compile with `tsc --strict test.ts`
export enum Type {
	FOO = 0,
	BAR = 1,
}

const Test = () => {
	// Change the following line to `let typeFilter: "FOO" | "BAR" = "FOO";` and it will work
	let typeFilter = "FOO";

	if (Type[typeFilter] != Type.FOO) {
		return;
	}
};

export default Test;

Actual behavior:

test.ts:9:11 - error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

9  if (Type[typeFilter] != Type.FOO) {
            ~~~~~~~~~~


Found 1 error.

Playground Link: Playground

Related Issues: Maybe #27297

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

Tái hiện báo cáo từ ví dụ test.ts được cung cấp bằng cách chạy tsc --strict và kiểm tra chẩn đoán tại Type[typeFilter]. Đọc đường dẫn kiểm tra kiểu của thao tác tra cứu ngược enum và issue liên quan #27297 trước khi quyết định liệu hành vi hay chỉ thông báo nên thay đổi; được xem là hoàn tất khi hành vi dự kiến đã được xác định và được bao phủ bởi một trường hợp hồi quy.

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
Khá rõ ràng
Mức phù hợp với người mới
35/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.