-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Covariance / Contravariance Annotations #1394
Comments
The assignments you've noted are by design. When checking assignability of function types their parameters are considered bivariant. So when assigning Co/contravariance is not an easy concept for a lot of folks to grasp (even though there is an intuitive nature to the assignment questions). Explicit annotations for them can be especially difficult for people to make use of (particularly if they have to author the annotations in their own code). C# has these types of annotations now but was highly successful for many years without the additional layer of checking the variance annotations afford. My gut feeling is that I would be surprised if these ended up in TypeScript given their complexity and how 'heavy' a concept they are. |
@danquirk I disagree that covariance/contravariance are such "heavy" concepts. In practice, it's generally just library authors that use them (not end users), and they're easy to ignore, so I don't think you're adding a burden to the language. Yet on the flip side, you're adding a lot of expressiveness to situations that would otherwise be less type safe. Also, at a syntax level- having optional keywords of "in" and an "out" seems to me to be as lightweight as language constructs get. I certainly wouldn't consider this feature high enough priority to want it added to the backlog anytime soon, but once TypeScript is more mature it could certainly be a useful addition. |
So, if go with some "strict" mode only, there's no way to annotate variance, because it shouldn't introduce any new keywords. I've read Function Argument Bivariance article, and it looks like the example might be rewritten more clear and useful without bivariance requirement: enum EventType { Mouse, Keyboard }
interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }
function listenEvent<TEvent extends Event>(eventType: EventType, handler: (n: TEvent) => void) {
/* ... */
}
listenEvent<MouseEvent>(EventType.Mouse, e => console.log(e.x + ',' + e.y)); @MgSam thanks for support. |
Outputs are always covariant and arguments are usually contravariant. The only point where we'd need an annotation is when an argument is also used as an output. I think it would be a lot easier to grasp if all type constructors and generics came equipped with their associated |
@metaweta callbacks are bivariant now. It also needs clarification/make stricter. |
I don't know what you mean by "callbacks are bivariant": variance is a concept that applies to a specific use of a type in a signature. I was suggesting that types used in arguments be contravariant by default; now that I think more about it, that would cause new errors in currently working code, which is unacceptable. To avoid the issue of a new keyword, I suggest using +/- like Scala does. How about a directive "use variance" to opt into that assumption? That way a library author can avoid having to add the contravariant modifier everywhere, while the user of the library doesn't have to worry about it. Directives are a part of ECMAScript specifically designed for this kind of scoped alteration of semantics. |
I mean that callback is an argument which is a function: class A { ... } class B extends A { ... } class C extends B { ... }
function f(callback: (b: B) => void) { ... }
f((x: A) => { ... }); // no error, callback accepts x: A, fair any B is A
f((x: C) => { ... }); // no error, callback accepts x: C, but it might be called with B which isn't C That's what "callback are bivariant" means. Regarding +/-, do you mean to use it with type specifier? Like: function f<T>(x: T-[], y: T) { x.push(y); } // y: T+, by default for function arguments
Which directives do you mean? |
The arrow functor is contravariant in its first argument and covariant in its second. Contravariance acts somewhat like multiplication by -1. In In
I mean to use it in the type parameters rather than the function signature: interface Foo <-A, +B> {
map<+C>(f:(a:A) => C): Foo<C, B>;
}
The directive |
I understand this. But now TS violates this rule in case of callbacks. I didn't say how it should work, I did say how it works now. |
Yikes! That's terrible. |
If function parameters weren't bivariant, |
I take back my "that's terrible" assesment; that would only be fair for a purely functional language. Every mutable data structure is going to have this trouble. Getters are covariant while setters are contravariant: given I think the article's right that the sound alternatives are too cumbersome for not enough benefit. |
@RyanCavanaugh I thought interface X<T> {
out(): T;
cb(cb: (v: T) => void)): void; // like Array.forEach
in(v: T): void; // like Array.push
}
var xdog: X<Dog>;
var xanimal = <X<Animal>>xdog; // is it convertible?
// out is convertible, fair - covariance
xanimal.out(); // <Dog>xdog.out(), ok
// cb is convertible, fair - covariance
xanimal.cb(animal => cb(animal)); // xdog.cb(dog => cb(<Animal>dog)), ok
// in is not convertible - contravariance, but no error
xanimal.in(animal); // it same as...
xdog.in(animal); // error -- animal is not a Dog, but same call to xanimal don't produce an error
// here is used bivariance, but it's not fair
xanimal.cb((dog: Dog) => ...); // no error due bivariance, but it should be So and my purpose to mark variables/parameters with variance modifier to make them convertible. |
And even more clear example of bivariance which shouldn't be: var f: (x: { x: number; }) => void;
var g: (x: { x: number; y: number; }) => void;
g = f; // fair
f = g; // no error, but it should be |
If I understand right, you're suggesting keywords that would construct the co- or contravariant supertype of a given generic type, somewhat like extracting the real and imaginary part of a complex number. I like that idea. |
Recently found similar issue, I guess. class Base { n() { return 0; }}
class Derived extends Base { m() { return 1; }}
var base = (b: Base) => b.n();
var derived = (d: Derived) => d.m();
base = derived;
base(new Base()); // TypeError: undefined is not a function (evaluating 'd.m()') Wondering if it could be fixed easily or not? |
Found an area where covariance (IIRC) would really help: strongly (and provably) typing the element tree. You could correctly narrow a vdom's children to only the correct types, so something like React could prevent say type Child = // things...
interface Attrs {
// things...
}
interface VNode<T extends string, A extends Attrs, C extends Child> {
type: T;
attrs: A;
children: C[];
}
export const m<T extends string, C extends Children>(type: T, c?: C | C[]): VNode<T, {}, C>;
export const m<T extends string, A extends Attrs, C extends Children>(type: T, a: A, c?: C | C[]): VNode<T, A, C>; In effect, with covariant types and what exists today (and enough patience - it'd take a long while), you could mostly prove the well-formedness of virtual DOM trees (minus quantity) and largely correctly type the DOM itself. I discovered this working on a vdom experiment, where components can be in charge of rendering themselves (mod tree diffing). I optimally want to track both permitted attributes and permitted children, so covariance would help. |
It's rather a simple tweak in the compiler code to turn off covariance for parameters. I tried it once to get a feeling of what it takes to be a happy owner of the code that works right. The biggest pain are the overloaded DOM event handlers lib.d.ts that wont compile after such tweak. I tend to think that using overloading was a poor design choice for event handlers, because effectively they are a bunch of separate functions (despite sharing the same name) rather than one with a base basic signature coupled tons of covariant overloads: |
With the recent addition of Are there any plans to also support co- and contra-variance for other types? (as reported in this issue)? Or nothing on the roadmap? |
@nicojs the original proposal seemed to suggest adding co/contra variant annotations as a means of opting out of unsoundness on a per type basis. With Could you clarify, are you asking if there are any remaining soundness holes, or asking for an explicit way to declare variance (in addition to the inferred behavior)? |
The proposal initially discussed here and later outlined primarily in #10717 is mostly concerned of use-site covariance annotations. The motivation use cases are still not addressed even with recent enstricten rules. The simplest example is an array type which can be used both co- and contravariantly. With the proposal an array of type |
@Igorbek Could you elaborate on how |
@isiahmeadows consider |
@Igorbek Re-read my comment. You missed my nuance between |
ah, sorry @isiahmeadows I thought you were asking in the context of my previous note about their differences. In fact, Actually, TS does not currently make function test<T>(a: Readonly<T[]>, v: T) {
a[0] = v; // no error
} In general, generic type variance has nothing to do with read/write-ability. interface X<T> {
value: T; // read-write field with T in covariant position for reads and in contravariant position for writes
set: (value: T) => void; // read-write field with T in contravariant position
}
type Readonly<X<T>> = { // effectively equivalent to this
readonly value: T; // this is now covariant in respect to T
readonly set: (value: T) => void; // read field with T in contravariant position
}
type X<out T> = {
readonly value T; // same as Readonly
writeonly set: (value: T) => void; // see the difference
}
type X<in T> = {
writeonly value T;
readonly set: (value: T) => void;
} And a final thing, even if in many respects having a readonly version is mostly what you want, a simple |
Okay, I'd find |
being fixed in #29435 |
In the case of arrays, why not prevent aliasing assignments that aren't invariant without an explicit cast?
Given TypeScript's support for generics, when are covariant arrays actually useful? |
success compile: /Users/yidafu/github/react/packages/scheduler/src/forks/SchedulerFeatureFlags.www.ts success compile: /Users/yidafu/github/react/packages/scheduler/src/TracingSubscriptions.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/scheduler/src/Tracing.js: line 12, column 26). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/scheduler/src/Tracing.ts success compile: /Users/yidafu/github/react/packages/scheduler/src/SchedulerFeatureFlags.ts success compile: /Users/yidafu/github/react/packages/react-is/src/ReactIs.ts success compile: /Users/yidafu/github/react/packages/scheduler/src/Scheduler.ts success compile: /Users/yidafu/github/react/packages/react/src/forks/ReactCurrentDispatcher.www.ts success compile: /Users/yidafu/github/react/packages/react/src/forwardRef.ts success compile: /Users/yidafu/github/react/packages/react/src/forks/ReactCurrentOwner.www.ts success compile: /Users/yidafu/github/react/packages/react/src/memo.ts success compile: /Users/yidafu/github/react/packages/react/src/React.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactContext.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactCreateRef.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactBaseClasses.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactChildren.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactCurrentDispatcher.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactCurrentOwner.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactDebugCurrentFrame.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactElement.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactElementValidator.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactHooks.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactLazy.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactNoopUpdateQueue.ts success compile: /Users/yidafu/github/react/packages/react/src/ReactSharedInternals.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/DOMPropertyOperations.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/getActiveElement.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/inputValueTracking.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/getNodeForCharacterOffset.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMComponentTree.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMClientInjection.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMFB.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMInput.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMOption.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMSelect.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMSelection.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMTextarea.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/setInnerHTML.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactInputSelection.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/setTextContent.ts Warning: Opaque types can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/client/ToStringValue.js: line 10, column 7). See microsoft/TypeScript#202 success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ToStringValue.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/validateDOMNesting.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/BeforeInputEventPlugin.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/ChangeEventPlugin.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/DOMEventPluginOrder.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/DOMTopLevelEventTypes.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/EnterLeaveEventPlugin.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/EventListener.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/forks/EventListener-www.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/FallbackCompositionState.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/getEventCharCode.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/getEventKey.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/getEventModifierState.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/getEventTarget.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/getVendorPrefixedEventName.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/isEventSupported.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/ReactBrowserEventEmitter.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/ReactDOMEventListener.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SelectEventPlugin.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SimpleEventPlugin.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticClipboardEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticCompositionEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticAnimationEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticDragEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticFocusEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticInputEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticKeyboardEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticMouseEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticPointerEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticTouchEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticTransitionEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticWheelEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/events/SyntheticUIEvent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/fire/ReactFireHostConfig.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/DOMMarkupOperations.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/escapeTextForBrowser.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/quoteAttributeValueForBrowser.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMFizzServerBrowser.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMFizzServerFormatConfig.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMFizzServerNode.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMNodeStreamRenderer.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMServerBrowser.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMServerNode.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactDOMStringRenderer.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactPartialRendererContext.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactPartialRendererHooks.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactThreadIDAllocator.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/assertValidProps.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/checkReact.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/createMicrosoftUnsafeLocalFunction.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/CSSProperty.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/CSSPropertyOperations.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/CSSShorthandProperty.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/dangerousStyleValue.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/DOMNamespaces.ts The following comments are not represented in leadingComments, trailingComments or innerComments of any node in the AST: [ { type: 'CommentLine', value: ' attributeNamespace', start: 6393, end: 6414, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 6850, end: 6871, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 7329, end: 7350, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 7900, end: 7921, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 8621, end: 8642, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 9275, end: 9296, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 9782, end: 9803, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 10233, end: 10254, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 10504, end: 10525, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 12777, end: 12798, loc: SourceLocation { start: [Position], end: [Position] } }, { type: 'CommentLine', value: ' attributeNamespace', start: 14306, end: 14327, loc: SourceLocation { start: [Position], end: [Position] } } ] Attempting to add them back into the AST Successfully backfilled comments into the AST Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 47, column 27). See microsoft/TypeScript#12936 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 48, column 2). See microsoft/TypeScript#1394 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 49, column 2). See microsoft/TypeScript#1394 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 50, column 2). See microsoft/TypeScript#1394 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 51, column 2). See microsoft/TypeScript#1394 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 52, column 2). See microsoft/TypeScript#1394 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/shared/DOMProperty.js: line 53, column 2). See microsoft/TypeScript#1394 success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/DOMProperty.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/HTMLNodeType.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/hyphenateStyleName.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/isCustomComponent.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/omittedCloseTags.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/possibleStandardNames.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/ReactControlledValuePropTypes.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/ReactDOMInvalidARIAHook.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/ReactDOMNullInputValuePropHook.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/validAriaProperties.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/voidElementTags.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/shared/warnValidStyle.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/unstable-native-dependencies/ReactDOMUnstableNativeDependencies.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberErrorDialog.native.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberErrorDialog.www.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.art.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.dom-browser.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.dom.ts /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.native.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.test.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.fabric.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.fire.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/maxSigned31BitInt.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactCapturedValue.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactCurrentFiber.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactDebugFiberPerf.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberContext.ts /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberDevToolsHook.js success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberErrorDialog.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberErrorLogger.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberExpirationTime.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHostConfig.ts /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHostContext.js success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHydrationContext.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberInstrumentation.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberLazyComponent.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberNewContext.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberPendingPriority.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiberReconciler.js: line 74, column 22). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberReconciler.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiberRoot.js: line 32, column 31). See microsoft/TypeScript#12936 Warning: Contravariance can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiberRoot.js: line 75, column 2). See microsoft/TypeScript#1394 Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiberRoot.js: line 92, column 40). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberRoot.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberStack.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiberSuspenseComponent.js: line 13, column 28). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberSuspenseComponent.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberTreeReflection.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactHookEffectTags.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactProfilerTimer.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactStrictModeWarnings.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactTypeOfMode.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOM.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMHostConfig.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/fire/ReactFire.ts /Users/yidafu/github/react/packages/react-dom/src/test-utils/ReactTestUtils.js Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-reconciler/src/ReactFiber.js: line 86, column 20). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiber.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberCompleteWork.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberUnwindWork.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactUpdateQueue.ts success compile: /Users/yidafu/github/react/packages/react-dom/src/client/ReactDOMComponent.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/react-dom/src/server/ReactPartialRenderer.js: line 403, column 3). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/react-dom/src/server/ReactPartialRenderer.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactChildFiber.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberClassComponent.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberCommitWork.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHooks.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberBeginWork.ts success compile: /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberScheduler.ts ➜ script-tools git:(master) ✗ node ./react-trans-flow-2-ts /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHostContext.js /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberDevToolsHook.js /Users/yidafu/github/react/packages/react-dom/src/test-utils/ReactTestUtils.js ➜ script-tools git:(master) ✗ node ./react-trans-flow-2-ts /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberDevToolsHook.js /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHostContext.js /Users/yidafu/github/react/packages/react-dom/src/test-utils/ReactTestUtils.js ➜ script-tools git:(master) ✗ node ./react-trans-flow-2-ts success compile: /Users/yidafu/github/react/packages/shared/describeComponentFrame.ts success compile: /Users/yidafu/github/react/packages/shared/ExecutionEnvironment.ts success compile: /Users/yidafu/github/react/packages/shared/forks/invariant.www.ts success compile: /Users/yidafu/github/react/packages/shared/forks/lowPriorityWarning.www.ts success compile: /Users/yidafu/github/react/packages/shared/forks/invokeGuardedCallbackImpl.www.ts success compile: /Users/yidafu/github/react/packages/shared/forks/object-assign.umd.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.native-fb.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.native-oss.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.persistent.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.readonly.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.test-renderer.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.test-renderer.www.ts success compile: /Users/yidafu/github/react/packages/shared/forks/ReactFeatureFlags.www.ts success compile: /Users/yidafu/github/react/packages/shared/forks/Scheduler.umd.ts success compile: /Users/yidafu/github/react/packages/shared/forks/SchedulerTracing.umd.ts success compile: /Users/yidafu/github/react/packages/shared/forks/warningWithoutStack.www.ts success compile: /Users/yidafu/github/react/packages/shared/HostConfigWithNoHydration.ts success compile: /Users/yidafu/github/react/packages/shared/getComponentName.ts success compile: /Users/yidafu/github/react/packages/shared/HostConfigWithNoMutation.ts success compile: /Users/yidafu/github/react/packages/shared/HostConfigWithNoPersistence.ts success compile: /Users/yidafu/github/react/packages/shared/invariant.ts success compile: /Users/yidafu/github/react/packages/shared/invokeGuardedCallbackImpl.ts success compile: /Users/yidafu/github/react/packages/shared/isTextInputElement.ts success compile: /Users/yidafu/github/react/packages/shared/isValidElementType.ts success compile: /Users/yidafu/github/react/packages/shared/lowPriorityWarning.ts success compile: /Users/yidafu/github/react/packages/shared/objectIs.ts success compile: /Users/yidafu/github/react/packages/shared/ReactElementType.ts success compile: /Users/yidafu/github/react/packages/shared/ReactErrorUtils.ts success compile: /Users/yidafu/github/react/packages/shared/ReactFeatureFlags.ts success compile: /Users/yidafu/github/react/packages/shared/ReactInstanceMap.ts success compile: /Users/yidafu/github/react/packages/shared/ReactLazyComponent.ts success compile: /Users/yidafu/github/react/packages/shared/ReactPortal.ts success compile: /Users/yidafu/github/react/packages/shared/reactProdInvariant.ts success compile: /Users/yidafu/github/react/packages/shared/ReactSharedInternals.ts success compile: /Users/yidafu/github/react/packages/shared/ReactSymbols.ts success compile: /Users/yidafu/github/react/packages/shared/ReactTreeTraversal.ts success compile: /Users/yidafu/github/react/packages/shared/ReactSideEffectTags.ts Warning: Exact types can't be expressed in TypeScript (at ../../../../../react/packages/shared/ReactTypes.js: line 78, column 24). See microsoft/TypeScript#12936 success compile: /Users/yidafu/github/react/packages/shared/ReactTypes.ts success compile: /Users/yidafu/github/react/packages/shared/ReactVersion.ts success compile: /Users/yidafu/github/react/packages/shared/shallowEqual.ts success compile: /Users/yidafu/github/react/packages/shared/ReactWorkTags.ts success compile: /Users/yidafu/github/react/packages/shared/warning.ts success compile: /Users/yidafu/github/react/packages/shared/warningWithoutStack.ts /Users/yidafu/github/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberHostContext.js /Users/yidafu/github/react/packages/react-reconciler/src/ReactFiberDevToolsHook.js /Users/yidafu/github/react/packages/react-dom/src/test-utils/ReactTestUtils.js
I am very excited to see that this will exist in future versions of TypeScript. For the time being, if you're looking for a hacky way to ensure contravariance, you can add something like this to a class:
Note that you can't make this private if you want the constraint to work across TS projects due to #38953 ; you might think it works in your same-project tests but not once it is encoded in |
(It's a question as well as a suggestion)
Update: a proposal #10717
I've supposed that for structural type system as TypeScript is, type variance isn't applicable since type-compatibility is checked by use.
But when I had read @RyanCavanaugh 's TypeScript 1.4 sneak peek (specifically 'Stricter Generics' section) I realized that there's some lack in this direction by design or implementation.
I wondered this code is compiled:
More clear code:
How could
B[]
be assignable toA[]
if at least on memberpush
is not compatible. ForB[].push
it expects parameters of typeB
, butA[].push
expectsA
and it's valid to call it withA
.To illustrate:
Do I understand it correctly that is by design?
I don't think it can be called type-safe.
Actually, such restriction that could make
B[]
to be unassignable toA[]
isn't desirable.To solve it I suggest to introduce variance on some level (variable/parameter, type?).
Syntax
I'm not sure where variance should be applied - to variable or type?
Looks like it closer to variable it self, so the syntax could be like:
Questions to clarification
in out
(fixed type)?in
norout
(open for upcast/downcast)?So this topic is a discussion point.
The text was updated successfully, but these errors were encountered: