• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Czy TypeScript może się domyślić typu w tym przypadku?

42 Warsaw Coding Academy
+3 głosów
480 wizyt
pytanie zadane 3 sierpnia 2022 w JavaScript przez rafal.budzis Szeryf (85,700 p.)

Hej chciałbym typować obiekt gdzie wartość każdego klucza powinna być sprawdzana oddzielnie. Wartości w obiekcie są takiego typu: 

interface Values<T extends any> {
    value: T;
    func: (p: T) => void;
    name: string;
}

Wartość value ma być takiego samego typu jak parametr w funkcji func

Chciałbym otypować na raz wszystkie klucze i zastanawiam czy się da. 

const obj: {
    [key: string]: Values<any>;
} = {
    aaa: {
        name: 'aaa',
        value: 123,
        func: (aaa: number) => {
            console.log(aaa);
        },
    },
    bbb: {
        name: 'bbb',
        value: '123',
        func: (aaa: string) => {
            console.log(aaa);
        },
    },
    ccc: {
        name: 'ccc',
        value: '123',
        // tu chce błąd bo value jest string a parametr jest number
        func: (aaa: number) => {
            console.log(aaa);
        },
    },
};


Da się coś w ten deseń zrobić ? Czy musze niestety wymieniać wszystkie klucze osobno? W taki sposób:

const obj: {
    aaa: Values<number>;
    bbb: Values<string>;
    ccc: Values<number>;
} = ...


 

komentarz 3 sierpnia 2022 przez Sadako Obywatel (1,240 p.)

I tak i nie.

Szablon values jest jak najbardziej poprawny i może dawać error gdy użyjesz innych typów.

const stringValue: Values<string> = {
    value:3,
    func : (p: string) => console.log(p),
    name: 'text' 
}

W tym przypadku error bedzie, że do value próbujemy przypisać 3 (number), a typ spodziewany to string. Ten przykład nie przechodzi bo wpisaliśmy Values<string>. Czyli dokładnie wpisaliśmy, że T ma być string. Analogiczny przykład, tylko, że z any przejdzie bez problemu (bo go nie ma :D)

const someValue: Values<any> = {
    value: 3,
    func : (p: string) => console.log(p),
    name: 'strange'
}

To działa jak trzeba. 3 jest number (czyli pasuje do any), funkcja akceptuje string (czyli pasuje do any).

Problem u Ciebie jest, że jawnie wpisałeś/wpisałaś Values<any>. To nic nie da, bo każde property bedzie Value<any>. Z drugiej strony nie możesz wpisać innej nazwy niż any, jeśli mają być tam różne typy, bo jaką ma mieć to nazwę? Value<domyśl się>?

To co próbujesz zrobić wygląda podejrzanie (nie mówie, że takie jest, bo nie wiem co chcesz zrobić - mówie tylko, że tak wygląda). Może jak napiszesz do czego Ci ma służyć ten obj, to ktoś bedzie w stanie Ci doradzić, rozwiązanie problemu w elegantszy sposób.

komentarz 3 sierpnia 2022 przez rafal.budzis Szeryf (85,700 p.)
edycja 3 sierpnia 2022 przez rafal.budzis

Mam sobie system kroków oparty o maszyne w xState i projekt w React. Każdy krok ma przypisane komponenty. Chciałbym dodać nowy komponent powiązany z innym. 

obecnie typ wygląda tak : 

interface ConfigutarionStep {
    label:string;
    isVisible: () => boolean;
    CurrentValueComponent: React.FC<{onClick: () => void}>;
    EditCompoinent: React.FC<{onClose: () => void>;
}

Po zmianach wygląda tak 

interface ConfigutarionStep<DetailsProps extends {[key:string]: any}> {
    label:string;
    isVisible: () => boolean;
    CurrentValueComponent: React.FC<{onClick: () => void}>;
    EditCompoinent: React.FC<{onClose: () => void, onOpenDetails: (props: DetailsProps) => void }>;
    DetailsComponent: React.FC<DetailsProps>;
}

Obecnie obiekt z krokami jest otypowany tak 
 

const STEPS: {
     [key in StepName]: ConfigutarionStep 
} = ...

Nie chciałbym rezygnować z StepName w typie aby TS pilnował tego miejsca podczas dodawania nowego kroku do maszyny stanów. Nie chciałbym też ręcznie wypisywać litani tych typów bo mam ponad 10 kroków. 

EDIT: Narazie wymyśliłem coś takiego 

const STEPS: {
    [key in StepName]: ConfigutarionStep<Props1> | ConfigutarionStep<Props2>;
 = ...

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+1 głos
1 odpowiedź 242 wizyt
pytanie zadane 15 maja 2022 w JavaScript przez Bakkit Dyskutant (7,600 p.)
+1 głos
0 odpowiedzi 290 wizyt
0 głosów
1 odpowiedź 166 wizyt
pytanie zadane 14 grudnia 2019 w JavaScript przez ShiroUmizake Nałogowiec (46,300 p.)

93,377 zapytań

142,379 odpowiedzi

322,528 komentarzy

62,727 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...