@@ -535,6 +535,30 @@ addObject(BUILTIN_SHAPES, BuiltInRefValueId, [
535535 [ '*' , { kind : 'Object' , shapeId : BuiltInRefValueId } ] ,
536536] ) ;
537537
538+ /**
539+ * MixedReadOnly =
540+ * | primitive
541+ * | simple objects (Record<string, MixedReadOnly>)
542+ * | Array<MixedReadOnly>
543+ *
544+ * APIs such as Relay — but also Flux and other data stores — often return a
545+ * union of types with some interesting properties in terms of analysis.
546+ *
547+ * Given this constraint, if data came from Relay, then we should be able to
548+ * infer things like `data.items.map(): Array`. That may seem like a leap at
549+ * first but remember, we assume you're not patching builtins. Thus the only way
550+ * data.items.map can exist and be a function, given the above set of data types
551+ * and builtin JS methods, is if `data.items` was an Array, and `data.items.map`
552+ * is therefore calling Array.prototype.map. Then we know that function returns
553+ * an Array as well. This relies on the fact that map() is being called, so if
554+ * data.items was some other type it would error at runtime - so it's sound.
555+ *
556+ * Note that this shape is currently only used for hook return values, which
557+ * means that it's safe to type aliasing method-call return kinds as `Frozen`.
558+ *
559+ * Also note that all newly created arrays from method-calls (e.g. `.map`)
560+ * have the appropriate mutable `BuiltInArray` shape
561+ */
538562addObject ( BUILTIN_SHAPES , BuiltInMixedReadonlyId , [
539563 [
540564 'toString' ,
@@ -546,6 +570,36 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
546570 returnValueKind : ValueKind . Primitive ,
547571 } ) ,
548572 ] ,
573+ [
574+ 'indexOf' ,
575+ addFunction ( BUILTIN_SHAPES , [ ] , {
576+ positionalParams : [ ] ,
577+ restParam : Effect . Read ,
578+ returnType : { kind : 'Primitive' } ,
579+ calleeEffect : Effect . Read ,
580+ returnValueKind : ValueKind . Primitive ,
581+ } ) ,
582+ ] ,
583+ [
584+ 'includes' ,
585+ addFunction ( BUILTIN_SHAPES , [ ] , {
586+ positionalParams : [ ] ,
587+ restParam : Effect . Read ,
588+ returnType : { kind : 'Primitive' } ,
589+ calleeEffect : Effect . Read ,
590+ returnValueKind : ValueKind . Primitive ,
591+ } ) ,
592+ ] ,
593+ [
594+ 'at' ,
595+ addFunction ( BUILTIN_SHAPES , [ ] , {
596+ positionalParams : [ Effect . Read ] ,
597+ restParam : null ,
598+ returnType : { kind : 'Object' , shapeId : BuiltInMixedReadonlyId } ,
599+ calleeEffect : Effect . Capture ,
600+ returnValueKind : ValueKind . Frozen ,
601+ } ) ,
602+ ] ,
549603 [
550604 'map' ,
551605 addFunction ( BUILTIN_SHAPES , [ ] , {
@@ -642,9 +696,9 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
642696 addFunction ( BUILTIN_SHAPES , [ ] , {
643697 positionalParams : [ ] ,
644698 restParam : Effect . ConditionallyMutate ,
645- returnType : { kind : 'Poly' } ,
699+ returnType : { kind : 'Object' , shapeId : BuiltInMixedReadonlyId } ,
646700 calleeEffect : Effect . ConditionallyMutate ,
647- returnValueKind : ValueKind . Mutable ,
701+ returnValueKind : ValueKind . Frozen ,
648702 noAlias : true ,
649703 mutableOnlyIfOperandsAreMutable : true ,
650704 } ) ,
0 commit comments