@prisma/ts-builders 6.13.0-dev.3 → 6.13.0-dev.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ConditionalType.d.ts +29 -0
- package/dist/ConditionalType.js +95 -0
- package/dist/ConditionalType.mjs +70 -0
- package/dist/ConditionalType.test.d.ts +1 -0
- package/dist/ConditionalType.test.js +114 -0
- package/dist/ConditionalType.test.mjs +113 -0
- package/dist/FunctionType.d.ts +1 -0
- package/dist/FunctionType.js +1 -0
- package/dist/FunctionType.mjs +1 -0
- package/dist/GenericParameter.d.ts +1 -1
- package/dist/IntersectionType.d.ts +13 -0
- package/dist/IntersectionType.js +74 -0
- package/dist/IntersectionType.mjs +49 -0
- package/dist/IntersectionType.test.d.ts +1 -0
- package/dist/IntersectionType.test.js +119 -0
- package/dist/IntersectionType.test.mjs +118 -0
- package/dist/TypeBuilder.d.ts +1 -0
- package/dist/TypeBuilder.js +1 -0
- package/dist/TypeBuilder.mjs +1 -0
- package/dist/UnionType.d.ts +1 -0
- package/dist/UnionType.js +1 -0
- package/dist/UnionType.mjs +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.mjs +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TypeBuilder } from './TypeBuilder';
|
|
2
|
+
import { Writer } from './Writer';
|
|
3
|
+
export declare class ConditionalType extends TypeBuilder {
|
|
4
|
+
#private;
|
|
5
|
+
needsParenthesisInUnion: boolean;
|
|
6
|
+
needsParenthesisInIntersection: boolean;
|
|
7
|
+
constructor(checkType: TypeBuilder, extendsType: TypeBuilder, trueType: TypeBuilder, falseType: TypeBuilder);
|
|
8
|
+
write(writer: Writer): void;
|
|
9
|
+
}
|
|
10
|
+
declare class ConditionalTypeBuilder {
|
|
11
|
+
check(checkType: TypeBuilder): ConditionalTypeBuilderWithCheckType;
|
|
12
|
+
}
|
|
13
|
+
declare class ConditionalTypeBuilderWithCheckType {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(checkType: TypeBuilder);
|
|
16
|
+
extends(extendsType: TypeBuilder): ConditionalTypeBuilderWithExtendsType;
|
|
17
|
+
}
|
|
18
|
+
declare class ConditionalTypeBuilderWithExtendsType {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(checkType: TypeBuilder, extendsType: TypeBuilder);
|
|
21
|
+
then(trueType: TypeBuilder): ConditionalTypeBuilderWithTrueType;
|
|
22
|
+
}
|
|
23
|
+
declare class ConditionalTypeBuilderWithTrueType {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(checkType: TypeBuilder, extendsType: TypeBuilder, trueType: TypeBuilder);
|
|
26
|
+
else(falseType: TypeBuilder): ConditionalType;
|
|
27
|
+
}
|
|
28
|
+
export declare function conditionalType(): ConditionalTypeBuilder;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var ConditionalType_exports = {};
|
|
20
|
+
__export(ConditionalType_exports, {
|
|
21
|
+
ConditionalType: () => ConditionalType,
|
|
22
|
+
conditionalType: () => conditionalType
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(ConditionalType_exports);
|
|
25
|
+
var import_TypeBuilder = require("./TypeBuilder");
|
|
26
|
+
class ConditionalType extends import_TypeBuilder.TypeBuilder {
|
|
27
|
+
needsParenthesisInUnion = true;
|
|
28
|
+
needsParenthesisInIntersection = true;
|
|
29
|
+
#checkType;
|
|
30
|
+
#extendsType;
|
|
31
|
+
#trueType;
|
|
32
|
+
#falseType;
|
|
33
|
+
constructor(checkType, extendsType, trueType, falseType) {
|
|
34
|
+
super();
|
|
35
|
+
this.#checkType = checkType;
|
|
36
|
+
this.#extendsType = extendsType;
|
|
37
|
+
this.#trueType = trueType;
|
|
38
|
+
this.#falseType = falseType;
|
|
39
|
+
}
|
|
40
|
+
write(writer) {
|
|
41
|
+
writer.write(this.#checkType);
|
|
42
|
+
writer.write(" extends ");
|
|
43
|
+
writer.write(this.#extendsType);
|
|
44
|
+
writer.write(" ? ");
|
|
45
|
+
writer.write(this.#trueType);
|
|
46
|
+
writer.write(" : ");
|
|
47
|
+
writer.write(this.#falseType);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
class ConditionalTypeBuilder {
|
|
51
|
+
check(checkType) {
|
|
52
|
+
return new ConditionalTypeBuilderWithCheckType(checkType);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
class ConditionalTypeBuilderWithCheckType {
|
|
56
|
+
#checkType;
|
|
57
|
+
constructor(checkType) {
|
|
58
|
+
this.#checkType = checkType;
|
|
59
|
+
}
|
|
60
|
+
extends(extendsType) {
|
|
61
|
+
return new ConditionalTypeBuilderWithExtendsType(this.#checkType, extendsType);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
class ConditionalTypeBuilderWithExtendsType {
|
|
65
|
+
#checkType;
|
|
66
|
+
#extendsType;
|
|
67
|
+
constructor(checkType, extendsType) {
|
|
68
|
+
this.#checkType = checkType;
|
|
69
|
+
this.#extendsType = extendsType;
|
|
70
|
+
}
|
|
71
|
+
then(trueType) {
|
|
72
|
+
return new ConditionalTypeBuilderWithTrueType(this.#checkType, this.#extendsType, trueType);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
class ConditionalTypeBuilderWithTrueType {
|
|
76
|
+
#checkType;
|
|
77
|
+
#extendsType;
|
|
78
|
+
#trueType;
|
|
79
|
+
constructor(checkType, extendsType, trueType) {
|
|
80
|
+
this.#checkType = checkType;
|
|
81
|
+
this.#extendsType = extendsType;
|
|
82
|
+
this.#trueType = trueType;
|
|
83
|
+
}
|
|
84
|
+
else(falseType) {
|
|
85
|
+
return new ConditionalType(this.#checkType, this.#extendsType, this.#trueType, falseType);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function conditionalType() {
|
|
89
|
+
return new ConditionalTypeBuilder();
|
|
90
|
+
}
|
|
91
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
92
|
+
0 && (module.exports = {
|
|
93
|
+
ConditionalType,
|
|
94
|
+
conditionalType
|
|
95
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { TypeBuilder } from "./TypeBuilder";
|
|
2
|
+
class ConditionalType extends TypeBuilder {
|
|
3
|
+
needsParenthesisInUnion = true;
|
|
4
|
+
needsParenthesisInIntersection = true;
|
|
5
|
+
#checkType;
|
|
6
|
+
#extendsType;
|
|
7
|
+
#trueType;
|
|
8
|
+
#falseType;
|
|
9
|
+
constructor(checkType, extendsType, trueType, falseType) {
|
|
10
|
+
super();
|
|
11
|
+
this.#checkType = checkType;
|
|
12
|
+
this.#extendsType = extendsType;
|
|
13
|
+
this.#trueType = trueType;
|
|
14
|
+
this.#falseType = falseType;
|
|
15
|
+
}
|
|
16
|
+
write(writer) {
|
|
17
|
+
writer.write(this.#checkType);
|
|
18
|
+
writer.write(" extends ");
|
|
19
|
+
writer.write(this.#extendsType);
|
|
20
|
+
writer.write(" ? ");
|
|
21
|
+
writer.write(this.#trueType);
|
|
22
|
+
writer.write(" : ");
|
|
23
|
+
writer.write(this.#falseType);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
class ConditionalTypeBuilder {
|
|
27
|
+
check(checkType) {
|
|
28
|
+
return new ConditionalTypeBuilderWithCheckType(checkType);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class ConditionalTypeBuilderWithCheckType {
|
|
32
|
+
#checkType;
|
|
33
|
+
constructor(checkType) {
|
|
34
|
+
this.#checkType = checkType;
|
|
35
|
+
}
|
|
36
|
+
extends(extendsType) {
|
|
37
|
+
return new ConditionalTypeBuilderWithExtendsType(this.#checkType, extendsType);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
class ConditionalTypeBuilderWithExtendsType {
|
|
41
|
+
#checkType;
|
|
42
|
+
#extendsType;
|
|
43
|
+
constructor(checkType, extendsType) {
|
|
44
|
+
this.#checkType = checkType;
|
|
45
|
+
this.#extendsType = extendsType;
|
|
46
|
+
}
|
|
47
|
+
then(trueType) {
|
|
48
|
+
return new ConditionalTypeBuilderWithTrueType(this.#checkType, this.#extendsType, trueType);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
class ConditionalTypeBuilderWithTrueType {
|
|
52
|
+
#checkType;
|
|
53
|
+
#extendsType;
|
|
54
|
+
#trueType;
|
|
55
|
+
constructor(checkType, extendsType, trueType) {
|
|
56
|
+
this.#checkType = checkType;
|
|
57
|
+
this.#extendsType = extendsType;
|
|
58
|
+
this.#trueType = trueType;
|
|
59
|
+
}
|
|
60
|
+
else(falseType) {
|
|
61
|
+
return new ConditionalType(this.#checkType, this.#extendsType, this.#trueType, falseType);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function conditionalType() {
|
|
65
|
+
return new ConditionalTypeBuilder();
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
ConditionalType,
|
|
69
|
+
conditionalType
|
|
70
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_ArrayType = require("./ArrayType");
|
|
4
|
+
var import_ConditionalType = require("./ConditionalType");
|
|
5
|
+
var import_FunctionType = require("./FunctionType");
|
|
6
|
+
var import_IntersectionType = require("./IntersectionType");
|
|
7
|
+
var import_NamedType = require("./NamedType");
|
|
8
|
+
var import_ObjectType = require("./ObjectType");
|
|
9
|
+
var import_Parameter = require("./Parameter");
|
|
10
|
+
var import_Property = require("./Property");
|
|
11
|
+
var import_stringify = require("./stringify");
|
|
12
|
+
var import_UnionType = require("./UnionType");
|
|
13
|
+
const A = (0, import_NamedType.namedType)("A");
|
|
14
|
+
const B = (0, import_NamedType.namedType)("B");
|
|
15
|
+
const C = (0, import_NamedType.namedType)("C");
|
|
16
|
+
const D = (0, import_NamedType.namedType)("D");
|
|
17
|
+
(0, import_vitest.test)("basic conditional type", () => {
|
|
18
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check(A).extends(B).then(C).else(D);
|
|
19
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"A extends B ? C : D"`);
|
|
20
|
+
});
|
|
21
|
+
(0, import_vitest.test)("with union type as check type", () => {
|
|
22
|
+
const union = (0, import_UnionType.unionType)(A).addVariant(B);
|
|
23
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check(union).extends(C).then((0, import_NamedType.namedType)("true")).else((0, import_NamedType.namedType)("false"));
|
|
24
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"A | B extends C ? true : false"`);
|
|
25
|
+
});
|
|
26
|
+
(0, import_vitest.test)("with array type as extends type", () => {
|
|
27
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check(A).extends((0, import_ArrayType.array)(B)).then((0, import_NamedType.namedType)("IsArray")).else((0, import_NamedType.namedType)("NotArray"));
|
|
28
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"A extends B[] ? IsArray : NotArray"`);
|
|
29
|
+
});
|
|
30
|
+
(0, import_vitest.test)("with object types", () => {
|
|
31
|
+
const objType = (0, import_ObjectType.objectType)().add((0, import_Property.property)("name", (0, import_NamedType.namedType)("string"))).add((0, import_Property.property)("age", (0, import_NamedType.namedType)("number")));
|
|
32
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check(A).extends(objType).then((0, import_NamedType.namedType)("IsObject")).else((0, import_NamedType.namedType)("NotObject"));
|
|
33
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`
|
|
34
|
+
"A extends {
|
|
35
|
+
name: string
|
|
36
|
+
age: number
|
|
37
|
+
} ? IsObject : NotObject"
|
|
38
|
+
`);
|
|
39
|
+
});
|
|
40
|
+
(0, import_vitest.test)("with function types", () => {
|
|
41
|
+
const funcType = (0, import_FunctionType.functionType)().addParameter((0, import_Parameter.parameter)("x", (0, import_NamedType.namedType)("string"))).setReturnType((0, import_NamedType.namedType)("number"));
|
|
42
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check(A).extends(funcType).then((0, import_NamedType.namedType)("IsFunction")).else((0, import_NamedType.namedType)("NotFunction"));
|
|
43
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"A extends (x: string) => number ? IsFunction : NotFunction"`);
|
|
44
|
+
});
|
|
45
|
+
(0, import_vitest.test)("nested conditional types", () => {
|
|
46
|
+
const innerConditional = (0, import_ConditionalType.conditionalType)().check(A).extends(B).then(C).else(D);
|
|
47
|
+
const outerConditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("string")).then(innerConditional).else((0, import_NamedType.namedType)("never"));
|
|
48
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(outerConditional)).toMatchInlineSnapshot(`"T extends string ? A extends B ? C : D : never"`);
|
|
49
|
+
});
|
|
50
|
+
(0, import_vitest.test)("with generic types", () => {
|
|
51
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("U")).then((0, import_NamedType.namedType)("T")).else((0, import_NamedType.namedType)("never"));
|
|
52
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends U ? T : never"`);
|
|
53
|
+
});
|
|
54
|
+
(0, import_vitest.test)("complex real-world example", () => {
|
|
55
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_ArrayType.array)((0, import_NamedType.namedType)("any"))).then((0, import_NamedType.namedType)("T[0]")).else((0, import_NamedType.namedType)("T"));
|
|
56
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends any[] ? T[0] : T"`);
|
|
57
|
+
});
|
|
58
|
+
(0, import_vitest.test)("with literal types", () => {
|
|
59
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)('"foo"')).then((0, import_NamedType.namedType)("true")).else((0, import_NamedType.namedType)("false"));
|
|
60
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends "foo" ? true : false"`);
|
|
61
|
+
});
|
|
62
|
+
(0, import_vitest.test)("with intersection types", () => {
|
|
63
|
+
const intersection = (0, import_IntersectionType.intersectionType)(A).addType(B);
|
|
64
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends(intersection).then((0, import_NamedType.namedType)("HasBoth")).else((0, import_NamedType.namedType)("NotBoth"));
|
|
65
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends A & B ? HasBoth : NotBoth"`);
|
|
66
|
+
});
|
|
67
|
+
(0, import_vitest.test)("with tuple types", () => {
|
|
68
|
+
const tupleType = (0, import_NamedType.namedType)("[string, number]");
|
|
69
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends(tupleType).then((0, import_NamedType.namedType)("IsTuple")).else((0, import_NamedType.namedType)("NotTuple"));
|
|
70
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends [string, number] ? IsTuple : NotTuple"`);
|
|
71
|
+
});
|
|
72
|
+
(0, import_vitest.test)("with keyof type", () => {
|
|
73
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("K")).extends((0, import_NamedType.namedType)("keyof T")).then((0, import_NamedType.namedType)("K")).else((0, import_NamedType.namedType)("never"));
|
|
74
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"K extends keyof T ? K : never"`);
|
|
75
|
+
});
|
|
76
|
+
(0, import_vitest.test)("with never type", () => {
|
|
77
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("never")).then((0, import_NamedType.namedType)("NeverReached")).else((0, import_NamedType.namedType)("NotNever"));
|
|
78
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends never ? NeverReached : NotNever"`);
|
|
79
|
+
});
|
|
80
|
+
(0, import_vitest.test)("with unknown type", () => {
|
|
81
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("unknown")).then((0, import_NamedType.namedType)("AlwaysTrue")).else((0, import_NamedType.namedType)("NeverReached"));
|
|
82
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends unknown ? AlwaysTrue : NeverReached"`);
|
|
83
|
+
});
|
|
84
|
+
(0, import_vitest.test)("with any type", () => {
|
|
85
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("any")).extends((0, import_NamedType.namedType)("T")).then((0, import_NamedType.namedType)("AnyExtendsT")).else((0, import_NamedType.namedType)("NotExtends"));
|
|
86
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"any extends T ? AnyExtendsT : NotExtends"`);
|
|
87
|
+
});
|
|
88
|
+
(0, import_vitest.test)("deeply nested conditional types", () => {
|
|
89
|
+
const deeplyNested = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("string")).then(
|
|
90
|
+
(0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("U")).extends((0, import_NamedType.namedType)("number")).then(
|
|
91
|
+
(0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("V")).extends((0, import_NamedType.namedType)("boolean")).then((0, import_NamedType.namedType)("AllMatch")).else((0, import_NamedType.namedType)("VNotBoolean"))
|
|
92
|
+
).else((0, import_NamedType.namedType)("UNotNumber"))
|
|
93
|
+
).else((0, import_NamedType.namedType)("TNotString"));
|
|
94
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(deeplyNested)).toMatchInlineSnapshot(
|
|
95
|
+
`"T extends string ? U extends number ? V extends boolean ? AllMatch : VNotBoolean : UNotNumber : TNotString"`
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
(0, import_vitest.test)("with template literal types", () => {
|
|
99
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("`prefix_${string}`")).then((0, import_NamedType.namedType)("HasPrefix")).else((0, import_NamedType.namedType)("NoPrefix"));
|
|
100
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends \`prefix_\${string}\` ? HasPrefix : NoPrefix"`);
|
|
101
|
+
});
|
|
102
|
+
(0, import_vitest.test)("with infer keyword", () => {
|
|
103
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("Promise<infer U>")).then((0, import_NamedType.namedType)("U")).else((0, import_NamedType.namedType)("never"));
|
|
104
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T extends Promise<infer U> ? U : never"`);
|
|
105
|
+
});
|
|
106
|
+
(0, import_vitest.test)("conditional type in union", () => {
|
|
107
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("string")).then((0, import_NamedType.namedType)("A")).else((0, import_NamedType.namedType)("B"));
|
|
108
|
+
const union = (0, import_UnionType.unionType)(conditional).addVariant((0, import_NamedType.namedType)("C"));
|
|
109
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(union)).toMatchInlineSnapshot(`"(T extends string ? A : B) | C"`);
|
|
110
|
+
});
|
|
111
|
+
(0, import_vitest.test)("with mapped type notation", () => {
|
|
112
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T[K]")).extends((0, import_NamedType.namedType)("Function")).then((0, import_NamedType.namedType)("K")).else((0, import_NamedType.namedType)("never"));
|
|
113
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(conditional)).toMatchInlineSnapshot(`"T[K] extends Function ? K : never"`);
|
|
114
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { array } from "./ArrayType";
|
|
3
|
+
import { conditionalType } from "./ConditionalType";
|
|
4
|
+
import { functionType } from "./FunctionType";
|
|
5
|
+
import { intersectionType } from "./IntersectionType";
|
|
6
|
+
import { namedType } from "./NamedType";
|
|
7
|
+
import { objectType } from "./ObjectType";
|
|
8
|
+
import { parameter } from "./Parameter";
|
|
9
|
+
import { property } from "./Property";
|
|
10
|
+
import { stringify } from "./stringify";
|
|
11
|
+
import { unionType } from "./UnionType";
|
|
12
|
+
const A = namedType("A");
|
|
13
|
+
const B = namedType("B");
|
|
14
|
+
const C = namedType("C");
|
|
15
|
+
const D = namedType("D");
|
|
16
|
+
test("basic conditional type", () => {
|
|
17
|
+
const conditional = conditionalType().check(A).extends(B).then(C).else(D);
|
|
18
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"A extends B ? C : D"`);
|
|
19
|
+
});
|
|
20
|
+
test("with union type as check type", () => {
|
|
21
|
+
const union = unionType(A).addVariant(B);
|
|
22
|
+
const conditional = conditionalType().check(union).extends(C).then(namedType("true")).else(namedType("false"));
|
|
23
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"A | B extends C ? true : false"`);
|
|
24
|
+
});
|
|
25
|
+
test("with array type as extends type", () => {
|
|
26
|
+
const conditional = conditionalType().check(A).extends(array(B)).then(namedType("IsArray")).else(namedType("NotArray"));
|
|
27
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"A extends B[] ? IsArray : NotArray"`);
|
|
28
|
+
});
|
|
29
|
+
test("with object types", () => {
|
|
30
|
+
const objType = objectType().add(property("name", namedType("string"))).add(property("age", namedType("number")));
|
|
31
|
+
const conditional = conditionalType().check(A).extends(objType).then(namedType("IsObject")).else(namedType("NotObject"));
|
|
32
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`
|
|
33
|
+
"A extends {
|
|
34
|
+
name: string
|
|
35
|
+
age: number
|
|
36
|
+
} ? IsObject : NotObject"
|
|
37
|
+
`);
|
|
38
|
+
});
|
|
39
|
+
test("with function types", () => {
|
|
40
|
+
const funcType = functionType().addParameter(parameter("x", namedType("string"))).setReturnType(namedType("number"));
|
|
41
|
+
const conditional = conditionalType().check(A).extends(funcType).then(namedType("IsFunction")).else(namedType("NotFunction"));
|
|
42
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"A extends (x: string) => number ? IsFunction : NotFunction"`);
|
|
43
|
+
});
|
|
44
|
+
test("nested conditional types", () => {
|
|
45
|
+
const innerConditional = conditionalType().check(A).extends(B).then(C).else(D);
|
|
46
|
+
const outerConditional = conditionalType().check(namedType("T")).extends(namedType("string")).then(innerConditional).else(namedType("never"));
|
|
47
|
+
expect(stringify(outerConditional)).toMatchInlineSnapshot(`"T extends string ? A extends B ? C : D : never"`);
|
|
48
|
+
});
|
|
49
|
+
test("with generic types", () => {
|
|
50
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("U")).then(namedType("T")).else(namedType("never"));
|
|
51
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends U ? T : never"`);
|
|
52
|
+
});
|
|
53
|
+
test("complex real-world example", () => {
|
|
54
|
+
const conditional = conditionalType().check(namedType("T")).extends(array(namedType("any"))).then(namedType("T[0]")).else(namedType("T"));
|
|
55
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends any[] ? T[0] : T"`);
|
|
56
|
+
});
|
|
57
|
+
test("with literal types", () => {
|
|
58
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType('"foo"')).then(namedType("true")).else(namedType("false"));
|
|
59
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends "foo" ? true : false"`);
|
|
60
|
+
});
|
|
61
|
+
test("with intersection types", () => {
|
|
62
|
+
const intersection = intersectionType(A).addType(B);
|
|
63
|
+
const conditional = conditionalType().check(namedType("T")).extends(intersection).then(namedType("HasBoth")).else(namedType("NotBoth"));
|
|
64
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends A & B ? HasBoth : NotBoth"`);
|
|
65
|
+
});
|
|
66
|
+
test("with tuple types", () => {
|
|
67
|
+
const tupleType = namedType("[string, number]");
|
|
68
|
+
const conditional = conditionalType().check(namedType("T")).extends(tupleType).then(namedType("IsTuple")).else(namedType("NotTuple"));
|
|
69
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends [string, number] ? IsTuple : NotTuple"`);
|
|
70
|
+
});
|
|
71
|
+
test("with keyof type", () => {
|
|
72
|
+
const conditional = conditionalType().check(namedType("K")).extends(namedType("keyof T")).then(namedType("K")).else(namedType("never"));
|
|
73
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"K extends keyof T ? K : never"`);
|
|
74
|
+
});
|
|
75
|
+
test("with never type", () => {
|
|
76
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("never")).then(namedType("NeverReached")).else(namedType("NotNever"));
|
|
77
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends never ? NeverReached : NotNever"`);
|
|
78
|
+
});
|
|
79
|
+
test("with unknown type", () => {
|
|
80
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("unknown")).then(namedType("AlwaysTrue")).else(namedType("NeverReached"));
|
|
81
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends unknown ? AlwaysTrue : NeverReached"`);
|
|
82
|
+
});
|
|
83
|
+
test("with any type", () => {
|
|
84
|
+
const conditional = conditionalType().check(namedType("any")).extends(namedType("T")).then(namedType("AnyExtendsT")).else(namedType("NotExtends"));
|
|
85
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"any extends T ? AnyExtendsT : NotExtends"`);
|
|
86
|
+
});
|
|
87
|
+
test("deeply nested conditional types", () => {
|
|
88
|
+
const deeplyNested = conditionalType().check(namedType("T")).extends(namedType("string")).then(
|
|
89
|
+
conditionalType().check(namedType("U")).extends(namedType("number")).then(
|
|
90
|
+
conditionalType().check(namedType("V")).extends(namedType("boolean")).then(namedType("AllMatch")).else(namedType("VNotBoolean"))
|
|
91
|
+
).else(namedType("UNotNumber"))
|
|
92
|
+
).else(namedType("TNotString"));
|
|
93
|
+
expect(stringify(deeplyNested)).toMatchInlineSnapshot(
|
|
94
|
+
`"T extends string ? U extends number ? V extends boolean ? AllMatch : VNotBoolean : UNotNumber : TNotString"`
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
test("with template literal types", () => {
|
|
98
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("`prefix_${string}`")).then(namedType("HasPrefix")).else(namedType("NoPrefix"));
|
|
99
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends \`prefix_\${string}\` ? HasPrefix : NoPrefix"`);
|
|
100
|
+
});
|
|
101
|
+
test("with infer keyword", () => {
|
|
102
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("Promise<infer U>")).then(namedType("U")).else(namedType("never"));
|
|
103
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T extends Promise<infer U> ? U : never"`);
|
|
104
|
+
});
|
|
105
|
+
test("conditional type in union", () => {
|
|
106
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("string")).then(namedType("A")).else(namedType("B"));
|
|
107
|
+
const union = unionType(conditional).addVariant(namedType("C"));
|
|
108
|
+
expect(stringify(union)).toMatchInlineSnapshot(`"(T extends string ? A : B) | C"`);
|
|
109
|
+
});
|
|
110
|
+
test("with mapped type notation", () => {
|
|
111
|
+
const conditional = conditionalType().check(namedType("T[K]")).extends(namedType("Function")).then(namedType("K")).else(namedType("never"));
|
|
112
|
+
expect(stringify(conditional)).toMatchInlineSnapshot(`"T[K] extends Function ? K : never"`);
|
|
113
|
+
});
|
package/dist/FunctionType.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare class FunctionType extends TypeBuilder {
|
|
|
6
6
|
needsParenthesisWhenIndexed: boolean;
|
|
7
7
|
needsParenthesisInKeyof: boolean;
|
|
8
8
|
needsParenthesisInUnion: boolean;
|
|
9
|
+
needsParenthesisInIntersection: boolean;
|
|
9
10
|
private returnType;
|
|
10
11
|
private parameters;
|
|
11
12
|
private genericParameters;
|
package/dist/FunctionType.js
CHANGED
|
@@ -28,6 +28,7 @@ class FunctionType extends import_TypeBuilder.TypeBuilder {
|
|
|
28
28
|
needsParenthesisWhenIndexed = true;
|
|
29
29
|
needsParenthesisInKeyof = true;
|
|
30
30
|
needsParenthesisInUnion = true;
|
|
31
|
+
needsParenthesisInIntersection = true;
|
|
31
32
|
returnType = import_PrimitiveType.voidType;
|
|
32
33
|
parameters = [];
|
|
33
34
|
genericParameters = [];
|
package/dist/FunctionType.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { NamedType } from './NamedType';
|
|
|
3
3
|
import { TypeBuilder } from './TypeBuilder';
|
|
4
4
|
import { Writer } from './Writer';
|
|
5
5
|
export declare class GenericParameter implements BasicBuilder {
|
|
6
|
-
|
|
6
|
+
readonly name: string;
|
|
7
7
|
private extendedType?;
|
|
8
8
|
private defaultType?;
|
|
9
9
|
constructor(name: string);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TypeBuilder } from './TypeBuilder';
|
|
2
|
+
import { Writer } from './Writer';
|
|
3
|
+
export declare class IntersectionType<MemberType extends TypeBuilder = TypeBuilder> extends TypeBuilder {
|
|
4
|
+
needsParenthesisWhenIndexed: boolean;
|
|
5
|
+
needsParenthesisInKeyof: boolean;
|
|
6
|
+
readonly members: MemberType[];
|
|
7
|
+
constructor(firstType: MemberType);
|
|
8
|
+
addType(type: MemberType): this;
|
|
9
|
+
addTypes(types: MemberType[]): this;
|
|
10
|
+
write(writer: Writer): void;
|
|
11
|
+
mapTypes<NewMemberType extends TypeBuilder>(callback: (type: MemberType) => NewMemberType): IntersectionType<NewMemberType>;
|
|
12
|
+
}
|
|
13
|
+
export declare function intersectionType<MemberType extends TypeBuilder = TypeBuilder>(types: MemberType[] | MemberType): IntersectionType<MemberType>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var IntersectionType_exports = {};
|
|
20
|
+
__export(IntersectionType_exports, {
|
|
21
|
+
IntersectionType: () => IntersectionType,
|
|
22
|
+
intersectionType: () => intersectionType
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(IntersectionType_exports);
|
|
25
|
+
var import_TypeBuilder = require("./TypeBuilder");
|
|
26
|
+
class IntersectionType extends import_TypeBuilder.TypeBuilder {
|
|
27
|
+
needsParenthesisWhenIndexed = true;
|
|
28
|
+
needsParenthesisInKeyof = true;
|
|
29
|
+
members;
|
|
30
|
+
constructor(firstType) {
|
|
31
|
+
super();
|
|
32
|
+
this.members = [firstType];
|
|
33
|
+
}
|
|
34
|
+
addType(type) {
|
|
35
|
+
this.members.push(type);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
addTypes(types) {
|
|
39
|
+
for (const type of types) {
|
|
40
|
+
this.addType(type);
|
|
41
|
+
}
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
write(writer) {
|
|
45
|
+
writer.writeJoined(" & ", this.members, (member, writer2) => {
|
|
46
|
+
if (member.needsParenthesisInIntersection) {
|
|
47
|
+
writer2.write("(").write(member).write(")");
|
|
48
|
+
} else {
|
|
49
|
+
writer2.write(member);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
mapTypes(callback) {
|
|
54
|
+
return intersectionType(this.members.map((m) => callback(m)));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function intersectionType(types) {
|
|
58
|
+
if (Array.isArray(types)) {
|
|
59
|
+
if (types.length === 0) {
|
|
60
|
+
throw new TypeError("Intersection types array can not be empty");
|
|
61
|
+
}
|
|
62
|
+
const intersection = new IntersectionType(types[0]);
|
|
63
|
+
for (let i = 1; i < types.length; i++) {
|
|
64
|
+
intersection.addType(types[i]);
|
|
65
|
+
}
|
|
66
|
+
return intersection;
|
|
67
|
+
}
|
|
68
|
+
return new IntersectionType(types);
|
|
69
|
+
}
|
|
70
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
71
|
+
0 && (module.exports = {
|
|
72
|
+
IntersectionType,
|
|
73
|
+
intersectionType
|
|
74
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TypeBuilder } from "./TypeBuilder";
|
|
2
|
+
class IntersectionType extends TypeBuilder {
|
|
3
|
+
needsParenthesisWhenIndexed = true;
|
|
4
|
+
needsParenthesisInKeyof = true;
|
|
5
|
+
members;
|
|
6
|
+
constructor(firstType) {
|
|
7
|
+
super();
|
|
8
|
+
this.members = [firstType];
|
|
9
|
+
}
|
|
10
|
+
addType(type) {
|
|
11
|
+
this.members.push(type);
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
addTypes(types) {
|
|
15
|
+
for (const type of types) {
|
|
16
|
+
this.addType(type);
|
|
17
|
+
}
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
write(writer) {
|
|
21
|
+
writer.writeJoined(" & ", this.members, (member, writer2) => {
|
|
22
|
+
if (member.needsParenthesisInIntersection) {
|
|
23
|
+
writer2.write("(").write(member).write(")");
|
|
24
|
+
} else {
|
|
25
|
+
writer2.write(member);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
mapTypes(callback) {
|
|
30
|
+
return intersectionType(this.members.map((m) => callback(m)));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function intersectionType(types) {
|
|
34
|
+
if (Array.isArray(types)) {
|
|
35
|
+
if (types.length === 0) {
|
|
36
|
+
throw new TypeError("Intersection types array can not be empty");
|
|
37
|
+
}
|
|
38
|
+
const intersection = new IntersectionType(types[0]);
|
|
39
|
+
for (let i = 1; i < types.length; i++) {
|
|
40
|
+
intersection.addType(types[i]);
|
|
41
|
+
}
|
|
42
|
+
return intersection;
|
|
43
|
+
}
|
|
44
|
+
return new IntersectionType(types);
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
IntersectionType,
|
|
48
|
+
intersectionType
|
|
49
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_ArrayType = require("./ArrayType");
|
|
4
|
+
var import_ConditionalType = require("./ConditionalType");
|
|
5
|
+
var import_FunctionType = require("./FunctionType");
|
|
6
|
+
var import_IntersectionType = require("./IntersectionType");
|
|
7
|
+
var import_NamedType = require("./NamedType");
|
|
8
|
+
var import_ObjectType = require("./ObjectType");
|
|
9
|
+
var import_Parameter = require("./Parameter");
|
|
10
|
+
var import_Property = require("./Property");
|
|
11
|
+
var import_stringify = require("./stringify");
|
|
12
|
+
var import_UnionType = require("./UnionType");
|
|
13
|
+
const A = (0, import_NamedType.namedType)("A");
|
|
14
|
+
const B = (0, import_NamedType.namedType)("B");
|
|
15
|
+
const C = (0, import_NamedType.namedType)("C");
|
|
16
|
+
(0, import_vitest.test)("one type", () => {
|
|
17
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)((0, import_IntersectionType.intersectionType)(A))).toMatchInlineSnapshot(`"A"`);
|
|
18
|
+
});
|
|
19
|
+
(0, import_vitest.test)("multiple types", () => {
|
|
20
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)((0, import_IntersectionType.intersectionType)(A).addType(B))).toMatchInlineSnapshot(`"A & B"`);
|
|
21
|
+
});
|
|
22
|
+
(0, import_vitest.test)("three types", () => {
|
|
23
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)((0, import_IntersectionType.intersectionType)(A).addType(B).addType(C))).toMatchInlineSnapshot(`"A & B & C"`);
|
|
24
|
+
});
|
|
25
|
+
(0, import_vitest.test)("from array", () => {
|
|
26
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)((0, import_IntersectionType.intersectionType)([A, B, C]))).toMatchInlineSnapshot(`"A & B & C"`);
|
|
27
|
+
});
|
|
28
|
+
(0, import_vitest.test)("with function type", () => {
|
|
29
|
+
const funcType = (0, import_FunctionType.functionType)().addParameter((0, import_Parameter.parameter)("x", (0, import_NamedType.namedType)("string"))).setReturnType((0, import_NamedType.namedType)("void"));
|
|
30
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)((0, import_IntersectionType.intersectionType)([A, B, funcType]))).toMatchInlineSnapshot(`"A & B & ((x: string) => void)"`);
|
|
31
|
+
});
|
|
32
|
+
(0, import_vitest.test)("with object types", () => {
|
|
33
|
+
const obj1 = (0, import_ObjectType.objectType)().add((0, import_Property.property)("name", (0, import_NamedType.namedType)("string")));
|
|
34
|
+
const obj2 = (0, import_ObjectType.objectType)().add((0, import_Property.property)("age", (0, import_NamedType.namedType)("number")));
|
|
35
|
+
const intersection = (0, import_IntersectionType.intersectionType)(obj1).addType(obj2);
|
|
36
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`
|
|
37
|
+
"{
|
|
38
|
+
name: string
|
|
39
|
+
} & {
|
|
40
|
+
age: number
|
|
41
|
+
}"
|
|
42
|
+
`);
|
|
43
|
+
});
|
|
44
|
+
(0, import_vitest.test)("with array types", () => {
|
|
45
|
+
const intersection = (0, import_IntersectionType.intersectionType)((0, import_ArrayType.array)(A)).addType((0, import_ArrayType.array)(B));
|
|
46
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"A[] & B[]"`);
|
|
47
|
+
});
|
|
48
|
+
(0, import_vitest.test)("with union types", () => {
|
|
49
|
+
const union1 = (0, import_UnionType.unionType)(A).addVariant(B);
|
|
50
|
+
const union2 = (0, import_UnionType.unionType)(C).addVariant((0, import_NamedType.namedType)("D"));
|
|
51
|
+
const intersection = (0, import_IntersectionType.intersectionType)(union1).addType(union2);
|
|
52
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"(A | B) & (C | D)"`);
|
|
53
|
+
});
|
|
54
|
+
(0, import_vitest.test)("fails with empty array", () => {
|
|
55
|
+
(0, import_vitest.expect)(() => (0, import_IntersectionType.intersectionType)([])).toThrowErrorMatchingInlineSnapshot(
|
|
56
|
+
`[TypeError: Intersection types array can not be empty]`
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
(0, import_vitest.test)("mapTypes", () => {
|
|
60
|
+
const intersection = (0, import_IntersectionType.intersectionType)([A, B, C]).mapTypes(import_ArrayType.array);
|
|
61
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"A[] & B[] & C[]"`);
|
|
62
|
+
});
|
|
63
|
+
(0, import_vitest.test)("with generic types", () => {
|
|
64
|
+
const intersection = (0, import_IntersectionType.intersectionType)((0, import_NamedType.namedType)("T")).addType((0, import_NamedType.namedType)("U"));
|
|
65
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"T & U"`);
|
|
66
|
+
});
|
|
67
|
+
(0, import_vitest.test)("with literal types", () => {
|
|
68
|
+
const intersection = (0, import_IntersectionType.intersectionType)((0, import_NamedType.namedType)('"foo"')).addType((0, import_NamedType.namedType)('"bar"'));
|
|
69
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`""foo" & "bar""`);
|
|
70
|
+
});
|
|
71
|
+
(0, import_vitest.test)("nested intersection types", () => {
|
|
72
|
+
const inner = (0, import_IntersectionType.intersectionType)(A).addType(B);
|
|
73
|
+
const outer = (0, import_IntersectionType.intersectionType)(inner).addType(C);
|
|
74
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(outer)).toMatchInlineSnapshot(`"A & B & C"`);
|
|
75
|
+
});
|
|
76
|
+
(0, import_vitest.test)("with conditional type", () => {
|
|
77
|
+
const conditional = (0, import_ConditionalType.conditionalType)().check((0, import_NamedType.namedType)("T")).extends((0, import_NamedType.namedType)("string")).then(A).else(B);
|
|
78
|
+
const intersection = (0, import_IntersectionType.intersectionType)(conditional).addType(C);
|
|
79
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"(T extends string ? A : B) & C"`);
|
|
80
|
+
});
|
|
81
|
+
(0, import_vitest.test)("with keyof type", () => {
|
|
82
|
+
const intersection = (0, import_IntersectionType.intersectionType)((0, import_NamedType.namedType)("keyof T")).addType((0, import_NamedType.namedType)("string"));
|
|
83
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"keyof T & string"`);
|
|
84
|
+
});
|
|
85
|
+
(0, import_vitest.test)("complex real-world example", () => {
|
|
86
|
+
const baseType = (0, import_ObjectType.objectType)().add((0, import_Property.property)("id", (0, import_NamedType.namedType)("string"))).add((0, import_Property.property)("createdAt", (0, import_NamedType.namedType)("Date")));
|
|
87
|
+
const userFields = (0, import_ObjectType.objectType)().add((0, import_Property.property)("name", (0, import_NamedType.namedType)("string"))).add((0, import_Property.property)("email", (0, import_NamedType.namedType)("string")));
|
|
88
|
+
const permissions = (0, import_ObjectType.objectType)().add(
|
|
89
|
+
(0, import_Property.property)("role", (0, import_UnionType.unionType)((0, import_NamedType.namedType)('"admin"')).addVariant((0, import_NamedType.namedType)('"user"')))
|
|
90
|
+
);
|
|
91
|
+
const userType = (0, import_IntersectionType.intersectionType)(baseType).addType(userFields).addType(permissions);
|
|
92
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(userType)).toMatchInlineSnapshot(`
|
|
93
|
+
"{
|
|
94
|
+
id: string
|
|
95
|
+
createdAt: Date
|
|
96
|
+
} & {
|
|
97
|
+
name: string
|
|
98
|
+
email: string
|
|
99
|
+
} & {
|
|
100
|
+
role: "admin" | "user"
|
|
101
|
+
}"
|
|
102
|
+
`);
|
|
103
|
+
});
|
|
104
|
+
(0, import_vitest.test)("addTypes with multiple types", () => {
|
|
105
|
+
const intersection = (0, import_IntersectionType.intersectionType)(A).addTypes([B, C]);
|
|
106
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"A & B & C"`);
|
|
107
|
+
});
|
|
108
|
+
(0, import_vitest.test)("with never type", () => {
|
|
109
|
+
const intersection = (0, import_IntersectionType.intersectionType)(A).addType((0, import_NamedType.namedType)("never"));
|
|
110
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"A & never"`);
|
|
111
|
+
});
|
|
112
|
+
(0, import_vitest.test)("with unknown type", () => {
|
|
113
|
+
const intersection = (0, import_IntersectionType.intersectionType)(A).addType((0, import_NamedType.namedType)("unknown"));
|
|
114
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"A & unknown"`);
|
|
115
|
+
});
|
|
116
|
+
(0, import_vitest.test)("with any type", () => {
|
|
117
|
+
const intersection = (0, import_IntersectionType.intersectionType)((0, import_NamedType.namedType)("any")).addType(B);
|
|
118
|
+
(0, import_vitest.expect)((0, import_stringify.stringify)(intersection)).toMatchInlineSnapshot(`"any & B"`);
|
|
119
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { array } from "./ArrayType";
|
|
3
|
+
import { conditionalType } from "./ConditionalType";
|
|
4
|
+
import { functionType } from "./FunctionType";
|
|
5
|
+
import { intersectionType } from "./IntersectionType";
|
|
6
|
+
import { namedType } from "./NamedType";
|
|
7
|
+
import { objectType } from "./ObjectType";
|
|
8
|
+
import { parameter } from "./Parameter";
|
|
9
|
+
import { property } from "./Property";
|
|
10
|
+
import { stringify } from "./stringify";
|
|
11
|
+
import { unionType } from "./UnionType";
|
|
12
|
+
const A = namedType("A");
|
|
13
|
+
const B = namedType("B");
|
|
14
|
+
const C = namedType("C");
|
|
15
|
+
test("one type", () => {
|
|
16
|
+
expect(stringify(intersectionType(A))).toMatchInlineSnapshot(`"A"`);
|
|
17
|
+
});
|
|
18
|
+
test("multiple types", () => {
|
|
19
|
+
expect(stringify(intersectionType(A).addType(B))).toMatchInlineSnapshot(`"A & B"`);
|
|
20
|
+
});
|
|
21
|
+
test("three types", () => {
|
|
22
|
+
expect(stringify(intersectionType(A).addType(B).addType(C))).toMatchInlineSnapshot(`"A & B & C"`);
|
|
23
|
+
});
|
|
24
|
+
test("from array", () => {
|
|
25
|
+
expect(stringify(intersectionType([A, B, C]))).toMatchInlineSnapshot(`"A & B & C"`);
|
|
26
|
+
});
|
|
27
|
+
test("with function type", () => {
|
|
28
|
+
const funcType = functionType().addParameter(parameter("x", namedType("string"))).setReturnType(namedType("void"));
|
|
29
|
+
expect(stringify(intersectionType([A, B, funcType]))).toMatchInlineSnapshot(`"A & B & ((x: string) => void)"`);
|
|
30
|
+
});
|
|
31
|
+
test("with object types", () => {
|
|
32
|
+
const obj1 = objectType().add(property("name", namedType("string")));
|
|
33
|
+
const obj2 = objectType().add(property("age", namedType("number")));
|
|
34
|
+
const intersection = intersectionType(obj1).addType(obj2);
|
|
35
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`
|
|
36
|
+
"{
|
|
37
|
+
name: string
|
|
38
|
+
} & {
|
|
39
|
+
age: number
|
|
40
|
+
}"
|
|
41
|
+
`);
|
|
42
|
+
});
|
|
43
|
+
test("with array types", () => {
|
|
44
|
+
const intersection = intersectionType(array(A)).addType(array(B));
|
|
45
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"A[] & B[]"`);
|
|
46
|
+
});
|
|
47
|
+
test("with union types", () => {
|
|
48
|
+
const union1 = unionType(A).addVariant(B);
|
|
49
|
+
const union2 = unionType(C).addVariant(namedType("D"));
|
|
50
|
+
const intersection = intersectionType(union1).addType(union2);
|
|
51
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"(A | B) & (C | D)"`);
|
|
52
|
+
});
|
|
53
|
+
test("fails with empty array", () => {
|
|
54
|
+
expect(() => intersectionType([])).toThrowErrorMatchingInlineSnapshot(
|
|
55
|
+
`[TypeError: Intersection types array can not be empty]`
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
test("mapTypes", () => {
|
|
59
|
+
const intersection = intersectionType([A, B, C]).mapTypes(array);
|
|
60
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"A[] & B[] & C[]"`);
|
|
61
|
+
});
|
|
62
|
+
test("with generic types", () => {
|
|
63
|
+
const intersection = intersectionType(namedType("T")).addType(namedType("U"));
|
|
64
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"T & U"`);
|
|
65
|
+
});
|
|
66
|
+
test("with literal types", () => {
|
|
67
|
+
const intersection = intersectionType(namedType('"foo"')).addType(namedType('"bar"'));
|
|
68
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`""foo" & "bar""`);
|
|
69
|
+
});
|
|
70
|
+
test("nested intersection types", () => {
|
|
71
|
+
const inner = intersectionType(A).addType(B);
|
|
72
|
+
const outer = intersectionType(inner).addType(C);
|
|
73
|
+
expect(stringify(outer)).toMatchInlineSnapshot(`"A & B & C"`);
|
|
74
|
+
});
|
|
75
|
+
test("with conditional type", () => {
|
|
76
|
+
const conditional = conditionalType().check(namedType("T")).extends(namedType("string")).then(A).else(B);
|
|
77
|
+
const intersection = intersectionType(conditional).addType(C);
|
|
78
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"(T extends string ? A : B) & C"`);
|
|
79
|
+
});
|
|
80
|
+
test("with keyof type", () => {
|
|
81
|
+
const intersection = intersectionType(namedType("keyof T")).addType(namedType("string"));
|
|
82
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"keyof T & string"`);
|
|
83
|
+
});
|
|
84
|
+
test("complex real-world example", () => {
|
|
85
|
+
const baseType = objectType().add(property("id", namedType("string"))).add(property("createdAt", namedType("Date")));
|
|
86
|
+
const userFields = objectType().add(property("name", namedType("string"))).add(property("email", namedType("string")));
|
|
87
|
+
const permissions = objectType().add(
|
|
88
|
+
property("role", unionType(namedType('"admin"')).addVariant(namedType('"user"')))
|
|
89
|
+
);
|
|
90
|
+
const userType = intersectionType(baseType).addType(userFields).addType(permissions);
|
|
91
|
+
expect(stringify(userType)).toMatchInlineSnapshot(`
|
|
92
|
+
"{
|
|
93
|
+
id: string
|
|
94
|
+
createdAt: Date
|
|
95
|
+
} & {
|
|
96
|
+
name: string
|
|
97
|
+
email: string
|
|
98
|
+
} & {
|
|
99
|
+
role: "admin" | "user"
|
|
100
|
+
}"
|
|
101
|
+
`);
|
|
102
|
+
});
|
|
103
|
+
test("addTypes with multiple types", () => {
|
|
104
|
+
const intersection = intersectionType(A).addTypes([B, C]);
|
|
105
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"A & B & C"`);
|
|
106
|
+
});
|
|
107
|
+
test("with never type", () => {
|
|
108
|
+
const intersection = intersectionType(A).addType(namedType("never"));
|
|
109
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"A & never"`);
|
|
110
|
+
});
|
|
111
|
+
test("with unknown type", () => {
|
|
112
|
+
const intersection = intersectionType(A).addType(namedType("unknown"));
|
|
113
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"A & unknown"`);
|
|
114
|
+
});
|
|
115
|
+
test("with any type", () => {
|
|
116
|
+
const intersection = intersectionType(namedType("any")).addType(B);
|
|
117
|
+
expect(stringify(intersection)).toMatchInlineSnapshot(`"any & B"`);
|
|
118
|
+
});
|
package/dist/TypeBuilder.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare abstract class TypeBuilder implements BasicBuilder {
|
|
|
5
5
|
needsParenthesisWhenIndexed: boolean;
|
|
6
6
|
needsParenthesisInKeyof: boolean;
|
|
7
7
|
needsParenthesisInUnion: boolean;
|
|
8
|
+
needsParenthesisInIntersection: boolean;
|
|
8
9
|
abstract write(writer: Writer): void;
|
|
9
10
|
subKey(key: string): KeyType;
|
|
10
11
|
writeIndexed(writer: Writer): void;
|
package/dist/TypeBuilder.js
CHANGED
|
@@ -27,6 +27,7 @@ class TypeBuilder {
|
|
|
27
27
|
needsParenthesisWhenIndexed = false;
|
|
28
28
|
needsParenthesisInKeyof = false;
|
|
29
29
|
needsParenthesisInUnion = false;
|
|
30
|
+
needsParenthesisInIntersection = false;
|
|
30
31
|
subKey(key) {
|
|
31
32
|
const { KeyType } = require("./KeyType");
|
|
32
33
|
return new KeyType(this, key);
|
package/dist/TypeBuilder.mjs
CHANGED
package/dist/UnionType.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Writer } from './Writer';
|
|
|
3
3
|
export declare class UnionType<VariantType extends TypeBuilder = TypeBuilder> extends TypeBuilder {
|
|
4
4
|
needsParenthesisWhenIndexed: boolean;
|
|
5
5
|
needsParenthesisInKeyof: boolean;
|
|
6
|
+
needsParenthesisInIntersection: boolean;
|
|
6
7
|
readonly variants: VariantType[];
|
|
7
8
|
constructor(firstType: VariantType);
|
|
8
9
|
addVariant(variant: VariantType): this;
|
package/dist/UnionType.js
CHANGED
|
@@ -26,6 +26,7 @@ var import_TypeBuilder = require("./TypeBuilder");
|
|
|
26
26
|
class UnionType extends import_TypeBuilder.TypeBuilder {
|
|
27
27
|
needsParenthesisWhenIndexed = true;
|
|
28
28
|
needsParenthesisInKeyof = true;
|
|
29
|
+
needsParenthesisInIntersection = true;
|
|
29
30
|
variants;
|
|
30
31
|
constructor(firstType) {
|
|
31
32
|
super();
|
package/dist/UnionType.mjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './ArraySpread';
|
|
|
3
3
|
export * from './ArrayType';
|
|
4
4
|
export * from './BasicBuilder';
|
|
5
5
|
export * from './Class';
|
|
6
|
+
export * from './ConditionalType';
|
|
6
7
|
export * from './ConstDeclaration';
|
|
7
8
|
export * from './DocComment';
|
|
8
9
|
export * from './Export';
|
|
@@ -14,6 +15,7 @@ export * from './GenericParameter';
|
|
|
14
15
|
export * from './helpers';
|
|
15
16
|
export * from './Import';
|
|
16
17
|
export * from './Interface';
|
|
18
|
+
export * from './IntersectionType';
|
|
17
19
|
export * from './KeyofType';
|
|
18
20
|
export * from './KeyType';
|
|
19
21
|
export * from './Method';
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ __reExport(index_exports, require("./ArraySpread"), module.exports);
|
|
|
20
20
|
__reExport(index_exports, require("./ArrayType"), module.exports);
|
|
21
21
|
__reExport(index_exports, require("./BasicBuilder"), module.exports);
|
|
22
22
|
__reExport(index_exports, require("./Class"), module.exports);
|
|
23
|
+
__reExport(index_exports, require("./ConditionalType"), module.exports);
|
|
23
24
|
__reExport(index_exports, require("./ConstDeclaration"), module.exports);
|
|
24
25
|
__reExport(index_exports, require("./DocComment"), module.exports);
|
|
25
26
|
__reExport(index_exports, require("./Export"), module.exports);
|
|
@@ -31,6 +32,7 @@ __reExport(index_exports, require("./GenericParameter"), module.exports);
|
|
|
31
32
|
__reExport(index_exports, require("./helpers"), module.exports);
|
|
32
33
|
__reExport(index_exports, require("./Import"), module.exports);
|
|
33
34
|
__reExport(index_exports, require("./Interface"), module.exports);
|
|
35
|
+
__reExport(index_exports, require("./IntersectionType"), module.exports);
|
|
34
36
|
__reExport(index_exports, require("./KeyofType"), module.exports);
|
|
35
37
|
__reExport(index_exports, require("./KeyType"), module.exports);
|
|
36
38
|
__reExport(index_exports, require("./Method"), module.exports);
|
|
@@ -57,6 +59,7 @@ __reExport(index_exports, require("./Writer"), module.exports);
|
|
|
57
59
|
...require("./ArrayType"),
|
|
58
60
|
...require("./BasicBuilder"),
|
|
59
61
|
...require("./Class"),
|
|
62
|
+
...require("./ConditionalType"),
|
|
60
63
|
...require("./ConstDeclaration"),
|
|
61
64
|
...require("./DocComment"),
|
|
62
65
|
...require("./Export"),
|
|
@@ -68,6 +71,7 @@ __reExport(index_exports, require("./Writer"), module.exports);
|
|
|
68
71
|
...require("./helpers"),
|
|
69
72
|
...require("./Import"),
|
|
70
73
|
...require("./Interface"),
|
|
74
|
+
...require("./IntersectionType"),
|
|
71
75
|
...require("./KeyofType"),
|
|
72
76
|
...require("./KeyType"),
|
|
73
77
|
...require("./Method"),
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./ArraySpread";
|
|
|
3
3
|
export * from "./ArrayType";
|
|
4
4
|
export * from "./BasicBuilder";
|
|
5
5
|
export * from "./Class";
|
|
6
|
+
export * from "./ConditionalType";
|
|
6
7
|
export * from "./ConstDeclaration";
|
|
7
8
|
export * from "./DocComment";
|
|
8
9
|
export * from "./Export";
|
|
@@ -14,6 +15,7 @@ export * from "./GenericParameter";
|
|
|
14
15
|
export * from "./helpers";
|
|
15
16
|
export * from "./Import";
|
|
16
17
|
export * from "./Interface";
|
|
18
|
+
export * from "./IntersectionType";
|
|
17
19
|
export * from "./KeyofType";
|
|
18
20
|
export * from "./KeyType";
|
|
19
21
|
export * from "./Method";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/ts-builders",
|
|
3
|
-
"version": "6.13.0-dev.
|
|
3
|
+
"version": "6.13.0-dev.30",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@prisma/internals": "6.13.0-dev.
|
|
27
|
+
"@prisma/internals": "6.13.0-dev.30"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"vitest": "3.0.9"
|