#Weird behavior when importing

7 messages · Page 1 of 1 (latest)

simple plank
#

I have a file with functions

// a.ts
export function foo(a: { test: number }): number {
  return 0
}
export function bar(a: { balls: string }): number {
  return 0
}

I have another file that takes the name of the function and calls it

// b.ts
import * as funcs from './a'

type Funcs = typeof funcs
type FuncName = keyof Funcs

function run<F extends FuncName>(func: F, params: Parameters<Funcs[F]>[0]) {
  return funcs[func](params)
  // funcs[func] has double params?
}

I am getting a strange error that:

Argument of type '{ test: number; } | { balls: string; }' is not assignable to parameter of type '{ test: number; } & { balls: string; }'.
  Type '{ test: number; }' is not assignable to type '{ test: number; } & { balls: string; }'.
    Property 'balls' is missing in type '{ test: number; }' but required in type '{ balls: string; }'```
vestal night
#

@simple plank Pretty sure this is

#

!retsam19:correspondence-problem

dark joltBOT
#
Retsam19#2505
`!retsam19:correspondence-problem`:

There's a particular pattern that is safe but hard for the Typescript compiler to handle, which I call the "correspondence problem":

const functionsWithArguments = [
  { func: (arg: string) => {}, arg: "foo" },
  { func: (arg: number) => {}, arg: 0 },
];

for (const { func, arg } of functionsWithArguments) {
  func(arg);
//     ^^^
// Argument of type 'string | number' is not assignable to parameter of type 'never'.
//   Type 'string' is not assignable to type 'never'.
}

The problem is that func is typed as (x: string) => void | (x: number) => void and arg is string | number, but the compiler can't prove that they "correspond": that, for example, arg is only a string when func accepts strings.

As far as the type are concerned, arg could be number, and func could be (arg: string) => void, and that would be a type-error. It's easy for us to see that that won't happen, but that requires understanding the program at a higher-level than the level the compiler operates.

Depending on the specifics there's sometimes clever fixes, but usually I recommend using a type assertion and ignoring the issue:

func(arg as never);
simple plank
simple plank
vestal night