简体   繁体   中英

Generic type inferred from wrong usage

As I understand, TS prefers direct type usages over "boxed" ones (eg in function) to infer a generic type from.

type Props<O, V> = {
  options: O[]
  getOptionValue: (o: O) => V
  value?: V
  onChange?: (v: V, o: O) => void
}

In this snippet type V is inferred from value field which is undesirable since value property is optional. Can I somehow force generic type inference to rely on getOptionValue property?

Sandbox example where if no value passed to a component its onChange argument v becomes unknown

I'm somewhat inclined to close this as a duplicate of this question . The compiler doesn't make multiple inference passes when trying to infer the types of a single object.

My workaround suggestion here would be the same as there: split your function into multiple parameters instead of a single parameter with multiple properties. You could even make a helper function like this:

const props = <O, V>(
    options: O[],
    getOptionValue: (o: O) => V,
    value?: V,
    onChange?: (v: V, o: O) => void
): Props<O, V> => ({ options, getOptionValue, onChange })

And then use it:

const theProps = props(
    [""],
    (o) => "test",
    undefined,
    (v, o) => v.length < o.length
);

Here you can see that O and V are properly inferred to be string and v is not unknown in the onChange callback. You can use also this with JSX via spread:

const c = <C {...theProps} />;

It's not perfect, since you're getting inference in exchange for a multi-step jsx element creation. But it does work.

Playground link to code

I don't think it's possible, because even if you remove the value property entirely typescript still won't use getOptionValue to infer the type.

function C<O, V>(props: {
    options: O[]
    getOptionValue: (o: O) => V
    onChange?: (v: V, o: O) => void
}) {}

C({
    options: [""],
    getOptionValue: (o) => "test",
    onChange: (v, o) => v.test // error: v is STILL 'unknown'
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM