Skip to content
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

Fix DeepPartial type #22789

Merged
merged 3 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions js/core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ export type Xor<T1, T2 = never, T3 = never, T4 = never, T5 = never, T6 = never,
| Seal<T8, KeysOf<T1, T2, T3, T4, T5, T6, T7, T9>>
| Seal<T9, KeysOf<T1, T2, T3, T4, T5, T6, T7, T8>>;

export type DeepPartial<T> = T extends object ? {
[P in keyof T]?: T[P] extends Function ? T[P] : DeepPartial<T[P]>;
} : T;
export type Scalar = undefined | null | string | String | number | Number | bigint | BigInteger | boolean | Boolean | Date | Function | Symbol | Array<unknown>;
export type DeepPartial<T> = T extends Scalar ? T : {
[P in keyof T]?: DeepPartial<T[P]>;
};

type ItemType<T> = T extends (infer TItem)[] ? TItem : T;
type Property<T, TPropName extends string> = T extends Partial<Record<TPropName, infer TValue>> ? TValue : never;
Expand Down
229 changes: 133 additions & 96 deletions testing/typescript/core.ts
Original file line number Diff line number Diff line change
@@ -1,107 +1,144 @@
/* eslint-disable import/no-duplicates */
/* eslint-disable import/first */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-type-alias */
import {
PropertyType,
} from '../../js/core';
/* eslint-disable @typescript-eslint/consistent-type-definitions */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable no-inner-declarations */

import {
assertType,
toAssertion,
} from './consts';

type ComplexType = {
a: {
b?: number | {
c: boolean;
};
import { Scalar } from '../../js/core';

{
interface TestInterface { i: any }
class TestClass { c: any; }
type TestType = { t: any };
function testFunction() {}

const scalar1: String extends Scalar ? true : false = true;
const scalar2: string extends Scalar ? true : false = true;
const scalar3: number extends Scalar ? true : false = true;
const scalar4: Number extends Scalar ? true : false = true;
const scalar5: bigint extends Scalar ? true : false = true;
const scalar6: BigInteger extends Scalar ? true : false = true;
const scalar7: Date extends Scalar ? true : false = true;
const scalar8: boolean extends Scalar ? true : false = true;
const scalar9: Boolean extends Scalar ? true : false = true;
const scalar10: null extends Scalar ? true : false = true;
const scalar11: undefined extends Scalar ? true : false = true;
const scalar12: Symbol extends Scalar ? true : false = true;
const scalar13: [] extends Scalar ? true : false = true;
const scalar14: (() => {}) extends Scalar ? true : false = true;
const scalar15: typeof testFunction extends Scalar ? true : false = true;
const scalar16: Symbol extends Scalar ? true : false = true;

const nonScalar1: TestInterface extends Scalar ? true : false = false;
const nonScalar2: TestClass extends Scalar ? true : false = false;
const nonScalar3: TestType extends Scalar ? true : false = false;
const nonScalar4: object extends Scalar ? true : false = false;
}

import { PropertyType } from '../../js/core';

{
type ComplexType = {
a: {
b?: number | {
c: boolean;
};
x: number;
} | { e: string };
}
| string
| {
d: boolean | string;
f: string | {
g: number | Record<number, boolean>;
}[];
};

type AExpected = {
b?: BExpected;
x: number;
} | { e: string };
type BExpected = number | { c: boolean };
type FExpected = string | { g: GExpected }[];
type GExpected = number | Record<number, boolean>;

const a1: AExpected = {
e: 'e',
};
const a2: AExpected = {
x: 42,
};
const a3: AExpected = {
x: 42,
b: 1,
};
const a4: AExpected = {
x: 42,
b: {
c: false,
},
};

assertType<AExpected>(toAssertion(a1));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a1));
assertType<AExpected>(toAssertion(a2));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a2));
assertType<AExpected>(toAssertion(a3));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a3));
assertType<AExpected>(toAssertion(a4));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a4));

const b1: BExpected = 42;
const b2: BExpected = { c: false };
assertType<BExpected>(toAssertion(b1));
assertType<PropertyType<ComplexType, 'a.b'>>(toAssertion(b1));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>>(toAssertion(b1));
assertType<BExpected>(toAssertion(b2));
assertType<PropertyType<ComplexType, 'a.b'>>(toAssertion(b2));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>>(toAssertion(b2));

assertType<boolean>(toAssertion(false));
assertType<PropertyType<ComplexType, 'a.b.c'>>(toAssertion(false));
assertType < PropertyType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>, 'c'>>(toAssertion(false));
assertType<boolean>(toAssertion(true));
assertType<PropertyType<ComplexType, 'a.b.c'>>(toAssertion(true));
assertType < PropertyType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>, 'c'>>(toAssertion(true));

assertType<boolean | string>(toAssertion(true));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion(true));
assertType<boolean | string>(toAssertion(false));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion(false));
assertType<boolean | string>(toAssertion('some string'));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion('some string'));

assertType<string>(toAssertion('some string'));
assertType<PropertyType<ComplexType, 'a.e'>>(toAssertion('some string'));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'e'>>(toAssertion('some string'));

const f1: FExpected = 'some string';
const f2: FExpected = [{ g: 42 }];
const f3: FExpected = [{ g: { 1: false, 2: false, 3: true } }];

assertType<FExpected>(toAssertion(f1));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f1));
assertType<FExpected>(toAssertion(f2));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f2));
assertType<FExpected>(toAssertion(f3));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f3));

const g1: GExpected = 42;
const g2: GExpected = { 1: false, 2: false, 3: true };
assertType<GExpected>(toAssertion(g1));
assertType<PropertyType<ComplexType, 'f.g'>>(toAssertion(g1));
assertType<PropertyType<PropertyType<ComplexType, 'f'>, 'g'>>(toAssertion(g1));
assertType<GExpected>(toAssertion(g2));
assertType<PropertyType<ComplexType, 'f.g'>>(toAssertion(g2));
assertType<PropertyType<PropertyType<ComplexType, 'f'>, 'g'>>(toAssertion(g2));
}
| string
| {
d: boolean | string;
f: string | {
g: number | Record<number, boolean>;
}[];
};

type AExpected = {
b?: BExpected;
x: number;
} | { e: string };
type BExpected = number | { c: boolean };
type FExpected = string | { g: GExpected }[];
type GExpected = number | Record<number, boolean>;

const a1: AExpected = {
e: 'e',
};
const a2: AExpected = {
x: 42,
};
const a3: AExpected = {
x: 42,
b: 1,
};
const a4: AExpected = {
x: 42,
b: {
c: false,
},
};

assertType<AExpected>(toAssertion(a1));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a1));
assertType<AExpected>(toAssertion(a2));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a2));
assertType<AExpected>(toAssertion(a3));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a3));
assertType<AExpected>(toAssertion(a4));
assertType<PropertyType<ComplexType, 'a'>>(toAssertion(a4));

const b1: BExpected = 42;
const b2: BExpected = { c: false };
assertType<BExpected>(toAssertion(b1));
assertType<PropertyType<ComplexType, 'a.b'>>(toAssertion(b1));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>>(toAssertion(b1));
assertType<BExpected>(toAssertion(b2));
assertType<PropertyType<ComplexType, 'a.b'>>(toAssertion(b2));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>>(toAssertion(b2));

assertType<boolean>(toAssertion(false));
assertType<PropertyType<ComplexType, 'a.b.c'>>(toAssertion(false));
assertType < PropertyType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>, 'c'>>(toAssertion(false));
assertType<boolean>(toAssertion(true));
assertType<PropertyType<ComplexType, 'a.b.c'>>(toAssertion(true));
assertType < PropertyType<PropertyType<PropertyType<ComplexType, 'a'>, 'b'>, 'c'>>(toAssertion(true));

assertType<boolean | string>(toAssertion(true));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion(true));
assertType<boolean | string>(toAssertion(false));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion(false));
assertType<boolean | string>(toAssertion('some string'));
assertType<PropertyType<ComplexType, 'd'>>(toAssertion('some string'));

assertType<string>(toAssertion('some string'));
assertType<PropertyType<ComplexType, 'a.e'>>(toAssertion('some string'));
assertType<PropertyType<PropertyType<ComplexType, 'a'>, 'e'>>(toAssertion('some string'));

const f1: FExpected = 'some string';
const f2: FExpected = [{ g: 42 }];
const f3: FExpected = [{ g: { 1: false, 2: false, 3: true } }];

assertType<FExpected>(toAssertion(f1));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f1));
assertType<FExpected>(toAssertion(f2));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f2));
assertType<FExpected>(toAssertion(f3));
assertType<PropertyType<ComplexType, 'f'>>(toAssertion(f3));

const g1: GExpected = 42;
const g2: GExpected = { 1: false, 2: false, 3: true };
assertType<GExpected>(toAssertion(g1));
assertType<PropertyType<ComplexType, 'f.g'>>(toAssertion(g1));
assertType<PropertyType<PropertyType<ComplexType, 'f'>, 'g'>>(toAssertion(g1));
assertType<GExpected>(toAssertion(g2));
assertType<PropertyType<ComplexType, 'f.g'>>(toAssertion(g2));
assertType<PropertyType<PropertyType<ComplexType, 'f'>, 'g'>>(toAssertion(g2));
14 changes: 9 additions & 5 deletions ts/dx.all.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1676,11 +1676,11 @@ declare module DevExpress.core {
/**
* @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution.
*/
export type DeepPartial<T> = T extends object
? {
[P in keyof T]?: T[P] extends Function ? T[P] : DeepPartial<T[P]>;
}
: T;
export type DeepPartial<T> = T extends Scalar
? T
: {
[P in keyof T]?: DeepPartial<T[P]>;
};
export type DefaultOptionsRule<T> = {
device?: Device | Device[] | ((device: Device) => boolean);
options: DeepPartial<T>;
Expand Down Expand Up @@ -1757,6 +1757,10 @@ declare module DevExpress.core {
* @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution.
*/
interface PromiseType<T> extends JQueryPromise<T> {}
/**
* @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution.
*/
type Scalar = string | number | Function | Date | Boolean | Array<unknown>;
/**
* [descr:template]
*/
Expand Down