Sử dụng ký hiệu làm loại khóa đối tượng trong TypeScript


20

Tôi đang cố gắng xác định một đối tượng có ký hiệu là loại khóa vì MDN nói:

Giá trị ký hiệu có thể được sử dụng làm định danh cho các thuộc tính đối tượng [...]

Nhưng sử dụng nó làm kiểu cho thuộc tính khóa:

type obj = {
    [key: symbol | string]: string
}

dẫn đến lỗi sau:

TS1023: Loại tham số chữ ký chỉ mục phải là 'chuỗi' hoặc 'số'.

thậm chí nó có thể được sử dụng như kiểu chỉ mục. Tôi đang sử dụng phiên bản bản thảo mới nhất ( v3.7.2), các câu hỏi liên quan tôi đã tìm thấy:

Tôi cũng đã xem qua các tài liệu ký hiệu bản thảo nhưng chúng chỉ cho thấy nó được sử dụng như thế nào chứ không phải là loại.

Thí dụ:

const obj = {} as {
    [key: number | symbol]: string // Won't work
};

const sym = Symbol('My symbol');
obj[sym] = 'Hi';

Sự cố trên Microsoft / TypeScript

Yêu cầu tính năng mở


Tôi nghĩ TypeScript chỉ hỗ trợ các ký hiệu cụ thể trong khai báo kiểu đối tượng của nó. Bạn có thực sự muốn bất kỳ symbol ? Có thể hiển thị một ví dụ về cách bạn muốn sử dụng của bạn type obj- Tôi nghi ngờ rằng tất cả các thuộc tính khóa ký hiệu sẽ là strings.
Bergi

@Bergi Tôi đã thêm một ví dụ, có thể tôi đã giám sát một cái gì đó nhưng tôi không thể tìm cách mang ts để chấp nhận một biểu tượng (mà không sử dụng anyđó là thông lệ xấu).
Simon


tôi không chắc liệu có đúng không nhưng bạn đã thử sử dụng Map<Symbol,String>như chúng tôi có Bản đồ chưa, nếu điều đó sẽ phục vụ mục đích của những gì bạn đang cố gắng đạt được
pavan kumar

Vấn đề tương tự đối với tôi, tôi đoán phần khó chịu là quảng cáo sai về cách "TS là một siêu ký tự của JS" - tốt, không chính xác. đây là một ví dụ hoàn hảo về điều đó
Patrick

Câu trả lời:


3

Thật không may, điều này là không thể vào lúc này trong TypeScript. Nếu bạn phải tương tác với một số API mong đợi điều này hoặc thực sự muốn sử dụng các biểu tượng làm khóa, bạn có thể thực hiện phiên bản khó xử này:

// Ensure we can not pass regular map to our custom functions
type SymbolMapTag = { readonly symbol: unique symbol }

type SymbolMap = SymbolMapTag & {
    [Key in string | number | symbol]: string;
}

function set_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym, value: T[TSym]) {
    target[sym] = value;
}

function get_symbol<T extends SymbolMap, TSym extends symbol>
(target: T, sym: TSym): T[TSym] {
    return target[sym];
}

const symbol_map = {} as SymbolMap;

const sym = Symbol('My symbol');
set_symbol(symbol_map, sym, "hi");
get_symbol(symbol_map, sym); // string


type NonSymbolMap = {
    [Key in string | number]: string;
}

const non_symbol_map = {} as NonSymbolMap;
set_symbol(non_symbol_map, sym, "hi"); // error
get_symbol(non_symbol_map, sym); // error
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.