Description
Strict Function Types
-
When we have a generic object type (e.g.
interface Foo<T, U> {}
, we've made the assumption thatT
andU
are covariant with respect toFoo
.- We based this on the fact that when comparing parameter types in functions, we do a bivariant comparison.
- Given this, relating type arguments covariantly should provide true positives, and we can fall back to a structural check when the check doesn't succeed.
-
However, now we are trying to introduce rules where parameters are (usually) strictly compared in a contravariant manner.
- This means we can no longer make that assumption.
- So what we do is we introduce two internal types, one which is a subtype of the other, and create two instantiations with each for each type parameter. We then do a structural comparison to see what the variance is based on relatability using each direction.
-
But there are places where this doesn't work out all that well.
interface Event<T> { target: T; } interface Base { onChange(ev: Event<Base>): void; } interface Derived extends Base { onChange(ev: Event<Derived>): void; }
- But this is not safe!
- So you could do one of two things:
- Say it's illegal, or declare these as
readonly
.interface Event<T> { target: T; } interface Base { writeonly onChange(ev: Event<Base>): void; } interface Derived extends Base { writeonly onChange(ev: Event<Derived>): void; }
- Say it's illegal, or declare these as
-
Current working proposal is that under
strictFunctionTypes
, the only types that get stricter are ones declared using- Arrow-style function types (
() => T
) - Arrow-style constructor types (
new () => T
) - Function expressions (arrow or classic-style)
- Function declarations
- Arrow-style function types (
-
However that means that
() => T
will no longer be equivalent to{ (): T }
under these rules. -
How plausible is it to turn this on by default?
- Not. Only under
--strict
.
- Not. Only under
-
We will definitely have to go over DefinitelyTyped to make sure this works okay.
-
For our declaration emitter, we need to make sure we emit the correct types.
Different diagnostic severities for noUnusedLocals
/noUnusedParameters
- Want to be able to get warnings for these errors.
- These features are anti-features anyway. These should be in a linter.
- Too late, we're arguably in lint-like territory and are already doing this.
- What about the
info
diagnostic?- One step at a time.
- So type errors become warnings, and
warnAsError
on by default? - Out of time.