How to check if a given value is in a union type array

后端 未结 3 776
醉梦人生
醉梦人生 2021-01-18 04:13

I have an array of given union type, then wants to check if a string from a superset of the union type is contained in the array (runtime check):



        
相关标签:
3条回答
  • 2021-01-18 04:50

    The biggest problem is how to handle all possible values that are not ConfigurationKeys without explicitly checking each one. I named them Configuration as it's very common scenario.

    You can hide logic behind your own guard function that tells compiler: I can handle type checks, trust me. It's recognized by value is ConfigurationKeys return type.

    Code example (live):

    type ConfigurationKeys = "foo" | "bar";
    
    function isConfiguration(value: string): value is ConfigurationKeys {
        const allowedKeys: string[] = ["foo", "bar"];
        
        return allowedKeys.indexOf(value) !== -1;
    }
    
    const key: string = "alien" // Rather: some random function
    
    if (isConfiguration(key)) { 
        // key => ConfigurationKeys
    } else { 
        // key => string
    }
    

    I found writing own guard functions as very clean solution to work with Union types. Sometimes type casting is still needed, but here you hide casting and logic within single piece of code.

    Reference:

    • User defined Type Guards
    • TypeScript doc: Type Guards and Differentiating Types
    0 讨论(0)
  • 2021-01-18 04:51

    I have found a potentially safer solution to this problem:

    const knownStrings = {
      abc: true,
      def: true,
    };
    
    const isKnownString = (name: string): name is keyof typeof knownStrings => name in knownStrings;
    

    This doesn't require any typecasting, the only downside is the redundant true values.

    0 讨论(0)
  • 2021-01-18 04:52

    The accepted answer uses type assertions/casting but from the comments it appears the OP went with a solution using find that works differently. I prefer that solution also, so here's how that can work:

    const configKeys = ['foo', 'bar'] as const;
    type ConfigKey = typeof configKeys[number]; // "foo" | "bar"
    
    // Return a typed ConfigKey from a string read at runtime (or throw if invalid).
    function getTypedConfigKey(maybeConfigKey: string): ConfigKey {
        const configKey = configKeys.find((validKey) => validKey === maybeConfigKey);
        if (configKey) {
            return configKey;
        }
        throw new Error(`String "${maybeConfigKey}" is not a valid config key.`);
    }
    

    Note that this can guarantee that a string is a valid ConfigKey both at runtime and compile time.

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