Używanie symbolu jako typu klucza obiektowego w TypeScript


20

Próbuję zdefiniować obiekt z symbolem jako klucz, ponieważ MDN mówi:

Wartość symbolu można wykorzystać jako identyfikator właściwości obiektu [...]

Ale używając go jako typu dla właściwości klucz:

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

powoduje następujący błąd:

TS1023: Typ parametru podpisu indeksu musi być „ciągiem” lub „liczbą”.

nawet może być użyty jako indeks. Korzystam z najnowszej wersji maszynopisu ( v3.7.2), powiązane pytania, które znalazłem:

Przyjrzałem się również dokumentom symboli maszynopisu, ale pokazują one tylko, w jaki sposób są używane jako wartość, a nie jako typ.

Przykład:

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

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

Problem dotyczący Microsoft / TypeScript

Otwórz żądanie funkcji


Myślę, że TypeScript obsługuje tylko określone symbole w deklaracjach typów obiektów. Naprawdę chcesz jakieś symbol ? Może pokaż przykład, w jaki sposób chcesz używać swojego type obj- wątpię, aby wszystkie właściwości z kluczem symbolicznym były strings.
— Bergi,

@Bergi Dodałem przykład, być może coś nadzorowałem, ale nie mogę znaleźć sposobu, aby zachęcić ts do przyjęcia symbolu (bez użycia, anyco jest złą praktyką).
— Simon


nie jestem pewien, czy Map<Symbol,String>mam rację, ale czy spróbowałeś użyć mapy, którą mamy, czy to by służyło celowi, który starasz się osiągnąć
— pavan kumar

Dla mnie ten sam problem, chyba denerwująca jest fałszywa reklama tego, jak „TS jest nadzbiorem JS” - cóż, niezupełnie. to jest tego doskonały przykład.
— Patrick

Odpowiedzi:


3

Niestety obecnie nie jest to możliwe w TypeScript. Jeśli musisz współpracować z niektórymi interfejsami API, które tego oczekują lub naprawdę chcesz używać symboli jako kluczy, możesz wykonać tę niezręczną wersję:

// 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.