Typescript: check if value is contained in type

后端 未结 4 678
青春惊慌失措
青春惊慌失措 2020-12-19 01:08

I have problem with defined types and checking if a value is contained in that type.

Here is my example:

these are the types:

export type Key         


        
相关标签:
4条回答
  • 2020-12-19 01:47

    If you check that the strings are the exact strings of the type, or if you check that they are not the strings that are not in the Key type it will work:

    export type Key = 'features' | 'special';
    
    export type TabTypes = 'info' | 'features' | 'special' | 'stars';
    function activeTabChanged(event: TabTypes) {
        var activeTab: TabTypes = event;
        if(event != 'info' && event != 'stars') {
            let key: Key = event;
        }
        // OR
        if(event == 'features' || event == 'special') {
            let key: Key = event;
        }
    }
    

    Edit

    The problem with the type definition is that it is erased at compile time, so at runtime there is no way to perform the check. A more verbose way of declaring the enum base on this page and a type guard can help acieve the effect:

    /** Utility function to create a K:V from a list of strings */
    function strEnum<T extends string>(o: Array<T>): {[K in T]: K} {
        return o.reduce((res, key) => {
        res[key] = key;
        return res;
        }, Object.create(null));
    }
    const Key = strEnum([
        'features',
        'special',
    ])
    type Key = keyof typeof Key;
    function isKey(key: string) : key is Key {
        return Key[key] !== undefined;
    }
    
    export type TabTypes = 'info' | 'features' | 'special' | 'stars';
    
    
    function activeTabChanged(event: TabTypes) {
        var activeTab: TabTypes = event;
        if(isKey(event)) {
            let key: Key = event;
        }
    }
    

    This example is worth it if the enums are large, otherwise the first version might work just as well.

    0 讨论(0)
  • 2020-12-19 01:51

    This answer to a similar question might be useful. it doesn't exactly answer your question, but it shows a similar way to achieve the desired result.

    In short, you can use array for inclusion checks, and type for type safety:

    const keys = <const> ['features','special'];
    export type Key = typeof keys[number];
    const tabTypes = <const> ['info' ,'features' ,'special', 'stars'];
    export type TabTypes = typeof tabTypes[number];
    
    activeTabChanged(event: TabTypes) {
        this.activeTab: TabTypes = event;
        // it won't let me set the key here because key has a different type 
        // but the send event can be contained in type Key
        // how can I check if the send event from type TabTypes is contained in type Key
    
        if (event in keys) {
            this.key: Key = event as Key;
        }
    }
    
    0 讨论(0)
  • 2020-12-19 02:03

    You could use a string enum.

    export enum Keys = {
      Features = 'features',
      Special = 'special',
    }
    
    // Compare it
    if (currentKey === Keys.Special) { console.log('Special key is set'); }
    

    In order to check if your value is defined in the predefined Enum at all you can do:

    if (currentKey in Keys) { console.log('valid key'); }
    
    0 讨论(0)
  • 2020-12-19 02:06

    2019 Solution:

    I had the same need and found an easier way to do that in another thread. In summary, what Patrick Roberts says in that link (updated with this question values) is:

    Don't over-complicate it.

    function isOfTypeTabs (keyInput: string): keyInput is TabTypes {
      return ['info', 'features', 'special', 'stars'].includes(keyInput);
    }
    

    See What does the `is` keyword do in typescript? for more information on why we don't just use a boolean return type.

    Credits and full source here: https://stackoverflow.com/a/57065680/6080254

    0 讨论(0)
提交回复
热议问题