8000 Using flow, Record#set and Record#merge return intersection types (v4) · Issue #1388 · immutable-js/immutable-js · GitHub
[go: up one dir, main page]

Skip to content
Using flow, Record#set and Record#merge return intersection types (v4) #1388
Closed
@acusti

Description

@acusti

What happened

In trying to upgrade draft-js to 4.0.0-rc.7 (and flow 0.57.1), I ran into many errors all around the fact that calling .set() or .merge() on a Record returns an intersection type that then causes errors for any other typing that refers to the original Record, or in the case of draft, that refers to a class that extends the Record, which is the common pattern in that codebase. For example:

ContentState.js, the Record-based class:

const defaultRecord: {
  entityMap: ?any,
  blockMap: ?BlockMap,
  selectionBefore: ?SelectionState,
  selectionAfter: ?SelectionState,
} = {
  entityMap: null,
  blockMap: null,
  selectionBefore: null,
  selectionAfter: null,
};

const ContentStateRecord = Record(defaultRecord);

class ContentState extends ContentStateRecord {
  ...
}

updateEntityDataInContentState.js:

import type ContentState from 'ContentState';

function updateEntityDataInContentState(
  contentState: ContentState,
  key: string,
  data: {[key: string]: any},
  merge: boolean,
): ContentState {
  const instance = contentState.getEntity(key);
  const entityData = instance.getData();
  const newData = merge ?
    {...entityData, ...data} :
    data;

  const newInstance = instance.set('data', newData);
  const newEntityMap = contentState.getEntityMap().set(key, newInstance);
  return contentState.set('entityMap', newEntityMap);
}

Which leads to:

Error: src/model/transaction/updateEntityDataInContentState.js:32
 32:   return contentState.set('entityMap', newEntityMap);
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ intersection. This type is incompatible with
 23: ): ContentState {
        ^^^^^^^^^^^^ ContentState
  Member 1:
  1395:   set<K: $Keys<T>>(key: K, value: $ElementType<T, K>): this & T;
                                                               ^^^^ `this` type. See: node_modules/immutable/dist/immutable.js.flow:1395
  Error:
  1395:   set<K: $Keys<T>>(key: K, value: $ElementType<T, K>): this & T;
                                                               ^^^^ RecordInstance. This type is incompatible with the expected return type of. See: node_modules/immutable/dist/immutable.js.flow:1395
   23: ): ContentState {
          ^^^^^^^^^^^^ ContentState
  Member 2:
   60: const ContentStateRecord = Record(defaultRecord);
                                  ^^^^^^^^^^^^^^^^^^^^^ type parameter `Values` of function call. See: src/model/immutable/ContentState.js:60
  Error:
  1387:   get<K: $Keys<T>>(key: K): $ElementType<T, K>;
                                    ^^^^^^^^^^^^^^^^^^ element type. Indexable signature not found in. See: node_modules/immutable/dist/immutable.js.flow:1387
   23: ): ContentState {
          ^^^^^^^^^^^^ ContentState

Is there a way to cast the result of every set and merge operation somehow to ensure that the value can still be typed as the original record type? Or any other recommended way to get around this issue?

Also, @leebyron, is opening issues here a useful way for me to report issues I come across as I work through getting draft.js upgraded (facebookarchive/draft-js#1439)? @flarnie mentioned that you were open to suggestions or questions; if there’s a better venue for that, please let me know. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0