Description
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!