#Trouble using generics on intersection of multiple types

8 messages · Page 1 of 1 (latest)

rigid wharf
#

Not sure how best to explain this but I have a "config" object.

const CONFIG = {
  hr: {
    prop1: "prop1val1",
  },
  div: {
    prop1: "prop1val2",
    prop2: 'prop1val1'
  },
};

The values objects share some of the keys. In the case above, its prop1

I want to create a function which takes a generic T extends keyof typeof CONFIG
and types an onChange function which can be used to set any of the overlapping/intersecting keys

this is what I have

type TConfig = typeof CONFIG;
type TConfigKeys = keyof TConfig;
type TConfigValues<T extends TConfigKeys> = TConfig[T];

type FnParams<T extends TConfigKeys> = {
  readonly onChange: (value: Partial<TConfigValues<T>>) => void;
};

const fn = <T extends TConfigKeys>({ onChange }: FnParams<T>) =>
  onChange({
    prop1: "solid",
  });

However I get an error
Argument of type '{ prop1: "solid"; }' is not assignable to parameter of type 'Partial<TConfigValues<T>>'
which I don't understand what the issue really is

gritty hollyBOT
#
krimson_21#0

Preview:```ts
const CONFIG = {
hr: {
prop1: "prop1val1",
},
div: {
prop1: "prop1val2",
prop2: "prop1val1",
},
}
type TConfig = typeof CONFIG
type TConfigKeys = keyof TConfig
type TConfigValues<T extends TConfigKeys> = TConfig[T]

type FnParams<T extends TConfigKeys> = {
rea
...```

rancid sage
#

i haven't found a counterexample for your specific code, and there's a chance this specific setup may actually be safe but TS isn't clever enough to notice. but do you need fn to be generic? this is probably a simplified example, but given what you've shared it could be:

const fn = ({ onChange }: FnParams<TConfigKeys>) =>
  onChange({
    prop1: "solid",
  });
limpid veldt
#

Does TS refuse it because it accounts for the T = never scenario?

gritty hollyBOT
#
sandiford#0

Preview:```ts
const CONFIG = {
hr: {
prop1: "prop1val1",
},
div: {
prop1: "prop1val2",
prop2: "prop1val1",
},
}
type TConfig = typeof CONFIG
type TConfigKeys = keyof TConfig
type TConfigValues<T extends TConfigKeys> = TConfig[T]

type FnParams<T extends TConfigKeys> = {
rea
...```

limpid veldt
#
const fn = <T extends TConfigKeys>({ onChange }: T extends never ? FnParams<'hr' | 'div'> : FnParams<T>) =>
  onChange({
    prop1: "solid",
  });

TS allows this

#

Not sure I agree with it's interfernce of the type of onChange though.

rigid wharf
#

but do you need fn to be generic?
You're totally right, it doesn't need to be a generic. Interesting problem nonetheless. I'll mark this as solved since I think the T = never seems reasonable