Comments (10)
Contravariance can be confusing but that's not typescript's fault.
from typescript.
Think of contravariance this way: let’s say I ask for something typed as
type Vet = (x: Animal) => Animal;
because I run a zoo and I have all sorts of animals. If what you give me instead is
type Specialist = (x: Dog | Cat) => Dog | Cat;
then that’s not going to work for me because I might need to pass in an Elephant
at some point. So the subtyping relationship turns upside down when you’re the one giving me things instead of you using them yourself.
from typescript.
This is working as intended. Your object does extend Record<string, any>
, but (props: ModalProps) => null
does not extend (props: Record<string, any>) => any
. When you disable strictFunctionTypes
it will work.
See also: https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant
This is the same issue simplified:
const val = 5 satisfies number
type Example<T extends (n: number) => any> = any
type Test = Example<(n: 5) => any>
from typescript.
@MartinJohns that's a really weird and confusing behaviour. Basically I have to either remove the constraint completely or replace Record<string, any>
with any
I still cannot get why (n: 5) => any does not satisfy (n: number) => any constraint, since 5 does satisfy number
I understand the intention of the strictFunctionTypes
flag but here it does not seem to be the case of use
from typescript.
By the way if you make all ModalProps
fields optional, then the error also goes away
from typescript.
type PropTypes<TFunctionComponent> =
TFunctionComponent extends (props: infer RProps) => any ? RProps extends Record<string, any> ? RProps : never : never;
Here is the best workaround I could have engineered for this case
from typescript.
I still cannot get why (n: 5) => any does not satisfy (n: number) => any constraint, since 5 does satisfy number
The type expects a function that can accept any number
, but the type passed is a function that can only accept one number (5
).
Your TFunctionComponent
expects a function that can accept any object (aka Record<string, any>
), but you pass Modal
, which is a function that expects at least ModelProps
.
Your best option is to simply have PropTypes<TFunctionComponent extends (props: any) => any>
.
from typescript.
I get your point. The confusion comes from that I read it in the opposing order: My TFunctionComponent
expects a function that can accept at least any object. ModalProps
is at least any object, so everything is expected to be okay
from typescript.
@fatcerberus thank you for the explication - I think I have to get used to it
from typescript.
Everybody trips over this at some point; I think it naturally confuses people because it doesn’t match how we talk about things day-to-day - in everyday language both Vet
and Specialist
would be described as types of doctors and what we need a doctor to be able to do is something we only care about when we call one - but in a type system those requirements are encoded right into the type so you end up having to care about them sooner…
from typescript.
Related Issues (20)
- `satisfies` operator could not completely overshadow the existing contextual type HOT 6
- Support conditional types for Generator T / TNext / TReturn HOT 3
- enum error HOT 2
- Class static side incorrectly extends mapped type in generic function HOT 4
- JScript Functions Support HOT 4
- Opt-in type checking of type safe type predicates HOT 4
- [ID-Prep] Preserve type nodes from function expressions in initialisers
- package.json#imports doesn't get IDE suggestions when typing the import path directly HOT 11
- Invalid ES2023 target suggested HOT 3
- Un-feature suggestion: relax type predicate construction rule
- Combining `importHelpers: true` and `module: preserve` results in TS2354
- Narrowed type not "carried" iteratively HOT 2
- Narrow generic mapped argument HOT 2
- `null` gets accidentally eliminated when narrowing by undefined's equality HOT 8
- No compilation error on later declared variable reference HOT 2
- Microsoft.TypeScript.MSBuild, need to find a way to delay execution of tsc HOT 2
- Excess and common property checks don't work correctly with `NoInfer`
- `tsc --watch` uses "incomplete" ANSI sequence for "clear buffer" HOT 2
- `tsc --watch` uses "incomplete" ANSI sequence for "clear buffer" HOT 5
- TS7022 circularity regression in 5.4.2 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typescript.