Home > OS >  How can I set up my function arg types to be mutually conditioned upon a config structure?
How can I set up my function arg types to be mutually conditioned upon a config structure?

Time:04-05

### this is my mapping data structure saying: some contexts have specific own tags
const config = {
  contexts: ["A", "B", "C"] as const,

  tags: {
    A: ["aa", "bb"] as const,
    B: ["aa1", "bb1"] as const,
    C: ["aa2", "bb2"] as const,
  },
};

# union type for contexts possible
type C = typeof config.contexts[number]; // "A" | "B" | "C"

# union type for tags specific for context U
type F<U extends C> = typeof config.tags[U][number];

const a: C = config.contexts[1]; // OK "B"

const f: F<typeof a> = "aa1"; // OK will accept only 'aa1','bb1'


# then I tried the above into a couple of function def but with NO SUCCESS

const func =  (a:C) => {
  return (g:F<typeof a>) => {}
}


func('A')(g) // ERROR g can be all of : "aa" | "bb" | "aa1" | "bb1" | "aa2" | "bb2"


const func2 =  (a:C,g:F<typeof a>) => {}


func('A',gg) // ERROR gg can be all of : "aa" | "bb" | "aa1" | "bb1" | "aa2" | "bb2"

CodePudding user response:

Using typoeof a does not mean capturing the actual type of the argument passed in, it just means whatever the declared type of a is, so in this case C. It works in the first case, because TS will use control flow analysis to narrow the type of a to B, since that is local information, but it will not work for functions.

To capture call site information, you need to use a type parameter:

const func =  <T extends C>(a:T) => {
  return (g:F<T>) => {}
}

func('A')("bb") // ok
func('A')("bb1") // err

Playground Link

  • Related