TypeScript: TS2322 error when using satisfies with strictFunctionTypes

🔎 Search Terms

satisfies strictFunctionTypes 2322

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about strictFunctionTypes

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.0-dev.20230821#code/C4TwDgpgBAYgrgOwMYAUBOB7MBnKBeKAbwCgoyoAzDDALim2DQEsEBzAbmIF9jikMEDKACMAhmnxQAFIUrUoXOvGTos2AJT4AfFAAGVWlAAkhA112cKiJMCYCRogF4y5GBUuuqcm2WgjA4NAQ9AzoTMwsFXn5BYEpBSRJyKGAIBgBGOjE0ABpSclSGACYspzyuelFbbAomNKgAJQh+NAATAB4GZjYc6SkwTBw6JpaOrpZWXsQAawQMAHcELU08HXG2dS12IA

💻 Code

type FuncProps = {
    foo: string;
}

const bar = ({ foo }: FuncProps) => `foo: ${foo}`;
function baz({ foo }: FuncProps) { return `foo: ${foo}`; }

const fns = {
    test1: bar,
    test2: baz,
} satisfies Record<string, ((props: Record<string, unknown>) => string)>;

🙁 Actual behavior

Type ‘({ foo }: FuncProps) => string’ is not assignable to type ‘(props: Record<string, unknown>) => string’. Types of parameters ‘__0’ and ‘props’ are incompatible. Property ‘foo’ is missing in type ‘Record<string, unknown>’ but required in type ‘FuncProps’.

🙂 Expected behavior

No error, I’m just using satisfies and type of __0 satisfies the one from props

Additional information about the issue

Using ((props: any) => string) “fixes” the error but is something I try to avoid

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Comments: 15 (4 by maintainers)

Most upvoted comments

satisfies following structure : a Record of functions with a unique parameter who extends Animal

Yeah, you can’t do that with an assignability check (which is all that satisfies is), because assignability goes in the opposite direction for function parameters, hence contravariance. AFAICT the check you want to do isn’t possible in the current type system.

So what you’re asking for, if I’m reading this right, is a way to say (using the animal analogy again):

  • “I want a function whose parameter is assignable to Animal, but the exact type of the parameter doesn’t matter.”

IMO it doesn’t really make sense to specify a type this way, since it doesn’t give you enough information to do anything with it. You couldn’t safely pass a random Animal to it, since it might require something specific (say, a Dog), but you also don’t know exactly what kind of animal it wants. Accordingly, there’s no way to specify this type (well… strictFunctionTypes: false allows it, but it’s unsound).

I don’t understand “satisfies” like that, especially when I’m able to use it the following way

Think of it this way: Dog is assignable to Animal because a dog is an animal, right? Anything you can do with any animal, you can do with a dog. But (x: Dog) => void is not assignable to (x: Animal) => void because someone might call the function with a cat, but your implementation can only deal with dogs.

This is called contravariance and is what strictFunctionTypes enforces.