Skip to content

Commit

Permalink
Rollback toJS type due to circular reference error (#1958)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdeniau committed Aug 25, 2023
1 parent 2306527 commit 1e2ec73
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 10 deletions.
18 changes: 15 additions & 3 deletions type-definitions/immutable.d.ts
Expand Up @@ -91,6 +91,16 @@
*/

declare namespace Immutable {
/** @ignore */
type OnlyObject<T> = Extract<T, object>;

/** @ignore */
type ContainObject<T> = OnlyObject<T> extends object
? OnlyObject<T> extends never
? false
: true
: false;

/**
* @ignore
*
Expand All @@ -100,14 +110,14 @@ declare namespace Immutable {
export type DeepCopy<T> = T extends Record<infer R>
? // convert Record to DeepCopy plain JS object
{
[key in keyof R]: DeepCopy<R[key]>;
[key in keyof R]: ContainObject<R[key]> extends true ? unknown : R[key];
}
: T extends Collection.Keyed<infer KeyedKey, infer V>
? // convert KeyedCollection to DeepCopy plain JS object
{
[key in KeyedKey extends string | number | symbol
? KeyedKey
: string]: DeepCopy<V>;
: string]: V extends object ? unknown : V;
}
: // convert IndexedCollection or Immutable.Set to DeepCopy plain JS array
T extends Collection<infer _, infer V>
Expand All @@ -118,7 +128,9 @@ declare namespace Immutable {
? Array<DeepCopy<V>>
: T extends object // plain JS object are converted deeply
? {
[ObjectKey in keyof T]: DeepCopy<T[ObjectKey]>;
[ObjectKey in keyof T]: ContainObject<T[ObjectKey]> extends true
? unknown
: T[ObjectKey];
}
: // other case : should be kept as is
T;
Expand Down
59 changes: 54 additions & 5 deletions type-definitions/ts-tests/deepCopy.ts
Expand Up @@ -23,10 +23,12 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable';
// $ExpectType { [x: string]: string; }
type StringKey = DeepCopy<Map<string, string>>;

// $ExpectType { [x: string]: object; }
// should be `{ [x: string]: object; }` but there is an issue with circular references
// $ExpectType { [x: string]: unknown; }
type ObjectKey = DeepCopy<Map<object, object>>;

// $ExpectType { [x: string]: object; [x: number]: object; }
// should be `{ [x: string]: object; [x: number]: object; }` but there is an issue with circular references
// $ExpectType { [x: string]: unknown; [x: number]: unknown; }
type MixedKey = DeepCopy<Map<object | number, object>>;

// $ExpectType string[]
Expand Down Expand Up @@ -55,10 +57,12 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable';
{
// Nested

// $ExpectType { map: { [x: string]: string; }; list: string[]; set: string[]; }
// should be `{ map: { [x: string]: string; }; list: string[]; set: string[]; }` but there is an issue with circular references
// $ExpectType { map: unknown; list: unknown; set: unknown; }
type NestedObject = DeepCopy<{ map: Map<string, string>; list: List<string>; set: Set<string>; }>;

// $ExpectType { map: { [x: string]: string; }; }
// should be `{ map: { [x: string]: string; }; }`, but there is an issue with circular references
// $ExpectType { map: unknown; }
type NestedMap = DeepCopy<Map<'map', Map<string, string>>>;
}

Expand All @@ -68,6 +72,51 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable';
type Article = Record<{ title: string; tag: Tag; }>;
type Tag = Record<{ name: string; article: Article; }>;

// $ExpectType { title: string; tag: { name: string; article: any; }; }
// should handle circular references here somehow
// $ExpectType { title: string; tag: unknown; }
type Circular = DeepCopy<Article>;
}

{
// Circular references #1957

class Foo1 extends Record<{
foo: undefined | Foo1;
}>({
foo: undefined
}) {
}

class Foo2 extends Record<{
foo?: Foo2;
}>({
foo: undefined
}) {
}

class Foo3 extends Record<{
foo: null | Foo3;
}>({
foo: null
}) {
}

// $ExpectType { foo: unknown; }
type DeepFoo1 = DeepCopy<Foo1>;

// $ExpectType { foo?: unknown; }
type DeepFoo2 = DeepCopy<Foo2>;

// $ExpectType { foo: unknown; }
type DeepFoo3 = DeepCopy<Foo3>;

class FooWithList extends Record<{
foos: undefined | List<FooWithList>;
}>({
foos: undefined
}) {
}

// $ExpectType { foos: unknown; }
type DeepFooList = DeepCopy<FooWithList>;
}
6 changes: 4 additions & 2 deletions type-definitions/ts-tests/record.ts
Expand Up @@ -88,7 +88,8 @@ import { List, Map, Record, RecordOf, Set } from 'immutable';
// $ExpectType { map: Map<string, string>; list: List<string>; set: Set<string>; }
withMap.toJSON();

// $ExpectType { map: { [x: string]: string; }; list: string[]; set: string[]; }
// should be `{ map: { [x: string]: string; }; list: string[]; set: string[]; }` but there is an issue with circular references
// $ExpectType { map: unknown; list: unknown; set: unknown; }
withMap.toJS();
}

Expand All @@ -101,7 +102,8 @@ import { List, Map, Record, RecordOf, Set } from 'immutable';

const line = Line({});

// $ExpectType { size?: { distance: string; } | undefined; color?: string | undefined; }
// should be { size?: { distance: string; } | undefined; color?: string | undefined; } but there is an issue with circular references
// $ExpectType { size?: unknown; color?: string | undefined; }
line.toJS();
}

Expand Down

0 comments on commit 1e2ec73

Please sign in to comment.