diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index 4939bfea76..f8c7a924a3 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -166,6 +166,7 @@ "@types/statuses": "2.0.1", "eslint-config-custom": "4.13.7", "supertest": "6.3.3", + "ts-zen": "https://github.com/strapi/ts-zen#66e02232f5997674cc7032ea3ee59d9864863732", "tsconfig": "4.13.7", "typescript": "5.2.2" }, diff --git a/packages/core/types/package.json b/packages/core/types/package.json index 20acab5885..57688274f5 100644 --- a/packages/core/types/package.json +++ b/packages/core/types/package.json @@ -53,7 +53,8 @@ "https-proxy-agent": "5.0.1", "koa": "2.13.4", "node-fetch": "2.7.0", - "node-schedule": "2.1.0" + "node-schedule": "2.1.0", + "ts-zen": "https://github.com/strapi/ts-zen#66e02232f5997674cc7032ea3ee59d9864863732" }, "devDependencies": { "@types/jest": "29.5.2", @@ -61,7 +62,6 @@ "@types/koa__router": "12.0.0", "@types/node-schedule": "2.1.0", "eslint-config-custom": "4.13.7", - "ts-zen": "https://github.com/strapi/ts-zen#66e02232f5997674cc7032ea3ee59d9864863732", "tsconfig": "4.13.7", "typescript": "5.2.2" }, diff --git a/packages/core/types/src/types/__tests__/definitions/utils/array.d.ts b/packages/core/types/src/types/__tests__/definitions/utils/array.d.ts new file mode 100644 index 0000000000..62b509d8ea --- /dev/null +++ b/packages/core/types/src/types/__tests__/definitions/utils/array.d.ts @@ -0,0 +1,46 @@ +import { Utils } from '../../..'; + +type Obj = { + foo: 'bar'; + baz: false; + prop: { + foo: 'bar'; + bar: 'foo'; + }; +}; + +type StringValues = Utils.Array.Values<['foo', 'bar', 'baz']>; +type NumberValues = Utils.Array.Values<[1, 2, 3]>; +type BoolValues = Utils.Array.Values<[true, false, true]>; +type TrueBoolLiteralValues = Utils.Array.Values<[true, true, true]>; +type FalseBoolLiteralValues = Utils.Array.Values<[false, false, false]>; +type ObjectValues = Utils.Array.Values<[Obj, { prop1: true; prop2: false }]>; +type MixedValues = Utils.Array.Values<[Obj, 1, 'foo', true]>; +type ContainsNever = Utils.Array.Values<[never, Obj, 1, 'foo', true]>; + +// TODO move this to tuple utils + +// Is Empty + +type IsEmptyWithEmptyTuple = Utils.Array.IsEmpty<[]>; +type IsEmptyWithNotEmptyTuple = Utils.Array.IsEmpty<['foo', 'bar']>; + +// Is Not Empty + +type IsNotEmptyWithNotEmptyTuple = Utils.Array.IsNotEmpty<['foo', 'bar']>; +type IsNotEmptyWithEmptyTuple = Utils.Array.IsNotEmpty<[]>; + +export { + StringValues, + NumberValues, + BoolValues, + TrueBoolLiteralValues, + FalseBoolLiteralValues, + ObjectValues, + MixedValues, + ContainsNever, + IsEmptyWithEmptyTuple, + IsEmptyWithNotEmptyTuple, + IsNotEmptyWithNotEmptyTuple, + IsNotEmptyWithEmptyTuple, +}; diff --git a/packages/core/types/src/types/__tests__/definitions/utils/expression.d.ts b/packages/core/types/src/types/__tests__/definitions/utils/expression.d.ts new file mode 100644 index 0000000000..00c1b09513 --- /dev/null +++ b/packages/core/types/src/types/__tests__/definitions/utils/expression.d.ts @@ -0,0 +1,341 @@ +import { Utils } from '../../..'; + +// IsNever +type IsNeverGivenNever = Utils.Expression.IsNever; +type IsNeverNotGivenNever = Utils.Expression.IsNever; +type IsNeverGivenUnknown = Utils.Expression.IsNever; + +// IsNotNever +type IsNotNeverGivenNever = Utils.Expression.IsNotNever; +type IsNotNeverGivenUnknown = Utils.Expression.IsNotNever; +type IsNotNeverGivenString = Utils.Expression.IsNotNever; +type IsNotNeverGivenStringLiteral = Utils.Expression.IsNotNever<'test'>; + +// IsTrue +type IsTrueGivenTrue = Utils.Expression.IsTrue; +type IsTrueGivenFalse = Utils.Expression.IsTrue; +type IsTrueGivenBoolean = Utils.Expression.IsTrue; +type IsTrueGivenNonBoolean = Utils.Expression.IsTrue; +type IsTrueGivenNonBooleanLiteral = Utils.Expression.IsTrue<10>; +type IsTrueGivenOne = Utils.Expression.IsTrue<1>; +type IsTrueGivenZero = Utils.Expression.IsTrue<0>; + +// IsFalse +type IsFalseGivenTrue = Utils.Expression.IsFalse; +type IsFalseGivenFalse = Utils.Expression.IsFalse; +type IsFalseGivenBoolean = Utils.Expression.IsFalse; +type IsFalseGivenNonBoolean = Utils.Expression.IsFalse; +type IsFalseGivenNonBooleanLiteral = Utils.Expression.IsFalse<10>; +type IsFalseGivenOne = Utils.Expression.IsFalse<1>; +type IsFalseGivenZero = Utils.Expression.IsFalse<0>; + +// Strict Equal +type IsStrictEqualGivenNever = Utils.Expression.StrictEqual; +type IsStrictEqualGivenNeverAndUnknown = Utils.Expression.StrictEqual; +type IsStrictEqualGivenEqualLiterals = Utils.Expression.StrictEqual<1, 1>; +type IsStrictEqualGivenEqualTypes = Utils.Expression.StrictEqual; +type IsStrictEqualGivenDifferentLiterals = Utils.Expression.StrictEqual<1, 2>; +type IsStrictEqualGivenDifferentTypes = Utils.Expression.StrictEqual; +type IsStrictEqualGivenStringAndStringLiteral = Utils.Expression.StrictEqual; +type IsStrictEqualGivenStringLiteralAndString = Utils.Expression.StrictEqual<'hello', string>; +type IsStrictEqualGivenNumberAndNumberLiteral = Utils.Expression.StrictEqual; +type IsStrictEqualGivenNumberLiteralAndNumber = Utils.Expression.StrictEqual<1, number>; + +// Extends +type StringExtendsString = Utils.Expression.Extends; +type StringLiteralExtendsString = Utils.Expression.Extends<'text', string>; +type StringExtendsStringLiteral = Utils.Expression.Extends; +type StringExtendsNumber = Utils.Expression.Extends; +type StringLiteralExtendsNumber = Utils.Expression.Extends<'text', number>; +type StringExtendsNumberLiteral = Utils.Expression.Extends; +type NumberExtendsNumber = Utils.Expression.Extends; +type NumberLiteralExtendsNumber = Utils.Expression.Extends<10, number>; +type NumberExtendsNumberLiteral = Utils.Expression.Extends; +type NumberExtendsString = Utils.Expression.Extends; +type NumberLiteralExtendsString = Utils.Expression.Extends<10, string>; +type NumberExtendsStringLiteral = Utils.Expression.Extends; +type ObjectExtendsObject = Utils.Expression.Extends; +type ObjectLiteralExtendsObject = Utils.Expression.Extends<{ test: 1 }, object>; +type ObjectExtendsObjectLiteral = Utils.Expression.Extends; +type ObjectExtendsNumber = Utils.Expression.Extends; +type ObjectExtendsAny = Utils.Expression.Extends; +type ObjectExtendsUnknown = Utils.Expression.Extends; +type ObjectExtendsNever = Utils.Expression.Extends; +type ArrayExtendsArray = Utils.Expression.Extends, Array>; +type TupleExtendsArray = Utils.Expression.Extends<[string], Array>; +type StringArrayExtendsArray = Utils.Expression.Extends>; + +// NotExtends +type StringNotExtendsString = Utils.Expression.DoesNotExtends; +type StringLiteralNotExtendsString = Utils.Expression.DoesNotExtends<'text', string>; +type StringNotExtendsStringLiteral = Utils.Expression.DoesNotExtends; +type StringNotExtendsNumber = Utils.Expression.DoesNotExtends; +type StringLiteralNotExtendsNumber = Utils.Expression.DoesNotExtends<'text', number>; +type StringNotExtendsNumberLiteral = Utils.Expression.DoesNotExtends; +type NumberNotExtendsNumber = Utils.Expression.DoesNotExtends; +type NumberLiteralNotExtendsNumber = Utils.Expression.DoesNotExtends<10, number>; +type NumberNotExtendsNumberLiteral = Utils.Expression.DoesNotExtends; +type NumberNotExtendsString = Utils.Expression.DoesNotExtends; +type NumberLiteralNotExtendsString = Utils.Expression.DoesNotExtends<10, string>; +type NumberNotExtendsStringLiteral = Utils.Expression.DoesNotExtends; +type ObjectNotExtendsObject = Utils.Expression.DoesNotExtends; +type ObjectLiteralNotExtendsObject = Utils.Expression.DoesNotExtends<{ test: 1 }, object>; +type ObjectNotExtendsObjectLiteral = Utils.Expression.DoesNotExtends; +type ObjectNotExtendsNumber = Utils.Expression.DoesNotExtends; +type ObjectNotExtendsAny = Utils.Expression.DoesNotExtends; +type ObjectNotExtendsUnknown = Utils.Expression.DoesNotExtends; +type ObjectNotExtendsNever = Utils.Expression.DoesNotExtends; +type ArrayNotExtendsArray = Utils.Expression.DoesNotExtends, Array>; +type TupleNotExtendsArray = Utils.Expression.DoesNotExtends<[string], Array>; +type StringArrayNotExtendsArray = Utils.Expression.DoesNotExtends>; + +// If +type IfTrue = Utils.Expression.If; +type IfFalse = Utils.Expression.If; +type IfBoolean = Utils.Expression.If; +type IfNumber = Utils.Expression.If; +type IfString = Utils.Expression.If; +type IfObject = Utils.Expression.If; +type IfUnknown = Utils.Expression.If; +type IfAny = Utils.Expression.If; +type IfNever = Utils.Expression.If; +type IfStringLiteral = Utils.Expression.If<'test', true, false>; +type IfNumberLiteral = Utils.Expression.If<10, true, false>; +type IfObjectLiteral = Utils.Expression.If<{ test: 1 }, true, false>; +type IfTuple = Utils.Expression.If<[1, 2, 3], true, false>; +type IfArray = Utils.Expression.If, true, false>; +type IfStringArray = Utils.Expression.If; +type IfTupleArray = Utils.Expression.If<[string, number], true, false>; +type IfUnion = Utils.Expression.If; +type IfIntersection = Utils.Expression.If; +type IfFunction = Utils.Expression.If<() => void, true, false>; +type IfClass = Utils.Expression.If void, true, false>; +type IfVoid = Utils.Expression.If; +type IfNull = Utils.Expression.If; +type IfUndefined = Utils.Expression.If; +type IfWithStringReturnType = Utils.Expression.If; +type IfWithNumberReturnType = Utils.Expression.If; +type IfWithBooleanReturnType = Utils.Expression.If; +type IfWithObjectReturnType = Utils.Expression.If; +type IfWithTupleReturnType = Utils.Expression.If; +// TODO Check this type +type IfWithArrayReturnType = Utils.Expression.If, Array>; +type IfWithUnionReturnType = Utils.Expression.If; +type IfWithVoidReturnType = Utils.Expression.If; +type IfWithNullReturnType = Utils.Expression.If; +type IfWithUndefinedReturnType = Utils.Expression.If; +type IfWithNeverReturnType = Utils.Expression.If; +type IfWithUnknownReturnType = Utils.Expression.If; +type IfWithAnyReturnType = Utils.Expression.If; + +// MatchFirst +type MatchFirstReturnsTestSuccessful = Utils.Expression.MatchFirst< + [[Utils.Expression.IsTrue, 'test-successful']], + 'fail' +>; +type MatchFirstReturnsDefault = Utils.Expression.MatchFirst< + [[Utils.Expression.IsTrue, 'test-successful']], + 'default' +>; +type MatchFirstReturnsNeverWithEmptyTests = Utils.Expression.MatchFirst<[], 'default'>; +type MatchFirstReturnsNeverWithNeverDefault = Utils.Expression.MatchFirst< + [[Utils.Expression.IsTrue, 'test-successful']], + never +>; + +// MatchAllIntersect +type MatchAllIntersectWithOneTrueCondition = Utils.Expression.MatchAllIntersect< + [ + [Utils.Expression.IsTrue, { test: 1 }], + [Utils.Expression.IsTrue, { test: 2 }] + ] +>; +type MatchAllIntersectWithAllFalseConditions = Utils.Expression.MatchAllIntersect< + [ + [Utils.Expression.IsTrue, { test: 1 }], + [Utils.Expression.IsTrue, { test: 2 }] + ] +>; + +type MatchAllIntersectWithIntersection = Utils.Expression.MatchAllIntersect< + [ + [Utils.Expression.Extends<'test', string>, 'test'], + [Utils.Expression.Extends<'test', string>, 'test'] + ] +>; + +// Test +type TestPasses = Utils.Expression.Test, 'test'>; +type TestFails = Utils.Expression.Test, 'test'>; + +// And +type AndTrue = Utils.Expression.And< + Utils.Expression.IsTrue, + Utils.Expression.IsTrue +>; +type AndFalse = Utils.Expression.And< + Utils.Expression.IsTrue, + Utils.Expression.IsTrue +>; + +// Or +type OrTrue = Utils.Expression.Or< + Utils.Expression.IsTrue, + Utils.Expression.IsTrue +>; + +type OrFalse = Utils.Expression.Or< + Utils.Expression.IsTrue, + Utils.Expression.IsTrue +>; + +type OrTrueFalse = Utils.Expression.Or< + Utils.Expression.IsTrue, + Utils.Expression.IsTrue +>; + +export { + // IsNever + IsNeverGivenNever, + IsNeverNotGivenNever, + IsNeverGivenUnknown, + // IsNotNever + IsNotNeverGivenNever, + IsNotNeverGivenUnknown, + IsNotNeverGivenString, + IsNotNeverGivenStringLiteral, + // Is Strict Equal + IsStrictEqualGivenNever, + IsStrictEqualGivenNeverAndUnknown, + IsStrictEqualGivenEqualLiterals, + IsStrictEqualGivenEqualTypes, + IsStrictEqualGivenDifferentLiterals, + IsStrictEqualGivenDifferentTypes, + IsStrictEqualGivenStringLiteralAndString, + IsStrictEqualGivenStringAndStringLiteral, + IsStrictEqualGivenNumberAndNumberLiteral, + IsStrictEqualGivenNumberLiteralAndNumber, + // IsTrue + IsTrueGivenTrue, + IsTrueGivenFalse, + IsTrueGivenBoolean, + IsTrueGivenNonBoolean, + IsTrueGivenNonBooleanLiteral, + IsTrueGivenOne, + IsTrueGivenZero, + // IsFalse + IsFalseGivenTrue, + IsFalseGivenFalse, + IsFalseGivenBoolean, + IsFalseGivenNonBoolean, + IsFalseGivenNonBooleanLiteral, + IsFalseGivenOne, + IsFalseGivenZero, + // Extends + StringExtendsString, + StringLiteralExtendsString, + StringExtendsStringLiteral, + StringExtendsNumber, + StringLiteralExtendsNumber, + StringExtendsNumberLiteral, + NumberExtendsNumber, + NumberLiteralExtendsNumber, + NumberExtendsNumberLiteral, + NumberExtendsString, + NumberLiteralExtendsString, + NumberExtendsStringLiteral, + ObjectExtendsObject, + ObjectLiteralExtendsObject, + ObjectExtendsObjectLiteral, + ObjectExtendsNumber, + ObjectExtendsAny, + ObjectExtendsUnknown, + ObjectExtendsNever, + ArrayExtendsArray, + TupleExtendsArray, + StringArrayExtendsArray, + // NotExtends + StringNotExtendsString, + StringLiteralNotExtendsString, + StringNotExtendsStringLiteral, + StringNotExtendsNumber, + StringLiteralNotExtendsNumber, + StringNotExtendsNumberLiteral, + NumberNotExtendsNumber, + NumberLiteralNotExtendsNumber, + NumberNotExtendsNumberLiteral, + NumberNotExtendsString, + NumberLiteralNotExtendsString, + NumberNotExtendsStringLiteral, + ObjectNotExtendsObject, + ObjectLiteralNotExtendsObject, + ObjectNotExtendsObjectLiteral, + ObjectNotExtendsNumber, + ObjectNotExtendsAny, + ObjectNotExtendsUnknown, + ObjectNotExtendsNever, + ArrayNotExtendsArray, + TupleNotExtendsArray, + StringArrayNotExtendsArray, + // If + IfTrue, + IfFalse, + IfBoolean, + IfNumber, + IfString, + IfObject, + IfUnknown, + IfAny, + IfNever, + IfStringLiteral, + IfNumberLiteral, + IfObjectLiteral, + IfTuple, + IfArray, + IfStringArray, + IfTupleArray, + IfUnion, + IfIntersection, + IfFunction, + IfClass, + IfVoid, + IfNull, + IfUndefined, + IfWithStringReturnType, + IfWithNumberReturnType, + IfWithBooleanReturnType, + IfWithObjectReturnType, + IfWithTupleReturnType, + IfWithArrayReturnType, + IfWithUnionReturnType, + IfWithVoidReturnType, + IfWithNullReturnType, + IfWithUndefinedReturnType, + IfWithNeverReturnType, + IfWithUnknownReturnType, + IfWithAnyReturnType, + + // MAtchFirst + MatchFirstReturnsTestSuccessful, + MatchFirstReturnsDefault, + MatchFirstReturnsNeverWithEmptyTests, + MatchFirstReturnsNeverWithNeverDefault, + + // MatchAllIntersect + MatchAllIntersectWithOneTrueCondition, + MatchAllIntersectWithAllFalseConditions, + MatchAllIntersectWithIntersection, + + // Test + TestPasses, + TestFails, + + // And + AndTrue, + AndFalse, + + // Or + OrTrue, + OrFalse, + OrTrueFalse, +}; diff --git a/packages/core/types/src/types/__tests__/definitions/utils/guard.d.ts b/packages/core/types/src/types/__tests__/definitions/utils/guard.d.ts new file mode 100644 index 0000000000..7e4a68725c --- /dev/null +++ b/packages/core/types/src/types/__tests__/definitions/utils/guard.d.ts @@ -0,0 +1,64 @@ +import { Utils } from '../../..'; + +// Never Guard +type NeverGuardGetsNeverWithDefaultFallback = Utils.Guard.Never; +type NeverGuardGetsNeverWithCustomFallback = Utils.Guard.Never; +type NeverGuardGetsAny = Utils.Guard.Never; +type NeverGuardGetsUnknown = Utils.Guard.Never; +type NeverGuardGetsNull = Utils.Guard.Never; +type NeverGuardGetsUndefined = Utils.Guard.Never; + +// OfTypes +// Single Type +type OfTypesNeverGetsNeverWithFallback = Utils.Guard.OfTypes<[never], never, string>; +type OfTypesNeverGetsNeverWithoutFallback = Utils.Guard.OfTypes<[never], never>; +type OfTypesUndefined = Utils.Guard.OfTypes<[undefined], undefined>; +type OfTypesUndefinedGetsString = Utils.Guard.OfTypes<[undefined], string>; +type OfTypesNull = Utils.Guard.OfTypes<[null], null>; +type OfTypesNullGetsString = Utils.Guard.OfTypes<[null], string>; +type OfTypesUnknown = Utils.Guard.OfTypes<[unknown], unknown, null>; +type OfTypesUnknownGetString = Utils.Guard.OfTypes<[unknown], string>; +type OfTypeUnionGetsMatchingUnion = Utils.Guard.OfTypes<[string | number], string | number>; +type OfTypeUnionGetsUnionElement = Utils.Guard.OfTypes<[string | number], string>; +// OfTypes<[any]> catches any given value +type OfTypesAnyGetsAny = Utils.Guard.OfTypes<[any], any>; +type OfTypesAnyGetsString = Utils.Guard.OfTypes<[any], string>; + +// Multiple Types + +type OfTypesStringAndNumberGetsString = Utils.Guard.OfTypes<[string, number], string>; +type OfTypesStringAndNumberGetsNumber = Utils.Guard.OfTypes<[string, number], string>; +type OfTypesStringAndNumberGetsUnionOfStringNumber = Utils.Guard.OfTypes< + [string, number], + string | number +>; +type OfTypesStringAndNumberGetsBoolean = Utils.Guard.OfTypes<[string, number], boolean>; + +export { + // Never + NeverGuardGetsNeverWithDefaultFallback, + NeverGuardGetsNeverWithCustomFallback, + NeverGuardGetsAny, + NeverGuardGetsUnknown, + NeverGuardGetsNull, + NeverGuardGetsUndefined, + // OfTypes + // Single Type + OfTypesNeverGetsNeverWithFallback, + OfTypesNeverGetsNeverWithoutFallback, + OfTypesAnyGetsAny, + OfTypesAnyGetsString, + OfTypesUndefined, + OfTypesUndefinedGetsString, + OfTypesNull, + OfTypesNullGetsString, + OfTypesUnknown, + OfTypesUnknownGetString, + OfTypeUnionGetsMatchingUnion, + OfTypeUnionGetsUnionElement, + // Multiple Types + OfTypesStringAndNumberGetsString, + OfTypesStringAndNumberGetsNumber, + OfTypesStringAndNumberGetsUnionOfStringNumber, + OfTypesStringAndNumberGetsBoolean, +}; diff --git a/packages/core/types/src/types/__tests__/definitions/utils/object.d.ts b/packages/core/types/src/types/__tests__/definitions/utils/object.d.ts new file mode 100644 index 0000000000..57d78294b6 --- /dev/null +++ b/packages/core/types/src/types/__tests__/definitions/utils/object.d.ts @@ -0,0 +1,59 @@ +import { Utils } from '../../..'; + +// Aux +type Base = { x: 'foo' | 'bar' }; +type Obj = { foo: { x: 'foo' }; bar: { x: 'bar' }; other: { x: '42' } }; + +// KeysBy +type KeysByString = Utils.Object.KeysBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, string>; +type KeysByNumber = Utils.Object.KeysBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, number>; +type KeysByNever = Utils.Object.KeysBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, never>; +type KeysByUnknown = Utils.Object.KeysBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, unknown>; +type KeysByObj = Utils.Object.KeysBy; + +// KeysExcept +type KeysExceptString = Utils.Object.KeysExcept<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, string>; +type KeysExceptNumber = Utils.Object.KeysExcept<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, number>; +type KeysExceptNever = Utils.Object.KeysExcept<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, never>; +type KeysExceptUnknown = Utils.Object.KeysExcept<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, unknown>; +type KeysExceptObj = Utils.Object.KeysExcept; + +// PickBy +type PickByString = Utils.Object.PickBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, string>; +type PickByNumber = Utils.Object.PickBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, number>; +type PickByNever = Utils.Object.PickBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, never>; +type PickByUnknown = Utils.Object.PickBy<{ foo: 'bar'; bar: 'foo'; foobar: 2 }, unknown>; +type PickByObj = Utils.Object.PickBy; + +// Values +type Values = Utils.Object.Values<{ foo: 'bar'; bar: 'foo'; foobar: 2 }>; +type ValuesNever = Utils.Object.Values; +type ValuesContainNever = Utils.Object.Values<{ foo: 'bar'; bar: 'foo'; foobar: never }>; + +export { + // KeysBy + KeysByString, + KeysByNumber, + KeysByNever, + KeysByUnknown, + KeysByObj, + + // KeysExcept + KeysExceptString, + KeysExceptNumber, + KeysExceptNever, + KeysExceptUnknown, + KeysExceptObj, + + // PickBy + PickByString, + PickByNumber, + PickByNever, + PickByUnknown, + PickByObj, + + // Values + Values, + ValuesNever, + ValuesContainNever, +}; diff --git a/packages/core/types/src/types/__tests__/test.utils.ts b/packages/core/types/src/types/__tests__/test.utils.ts new file mode 100644 index 0000000000..fb1a1a49c6 --- /dev/null +++ b/packages/core/types/src/types/__tests__/test.utils.ts @@ -0,0 +1,12 @@ +import path from 'path'; +import { fromFile } from 'ts-zen'; + +const DEFINITIONS_ROOT = path.join(__dirname, 'definitions'); + +export const createTypeSelector = (filePath: string) => { + // TODO: Remove when strapi/strapi is migrated to TS + return fromFile(path.join(DEFINITIONS_ROOT, filePath), { + compilerOptions: { strict: true }, + ignoreProjectOptions: true, + }); +}; diff --git a/packages/core/types/src/types/__tests__/utils/array.test.ts b/packages/core/types/src/types/__tests__/utils/array.test.ts new file mode 100644 index 0000000000..6a672885e6 --- /dev/null +++ b/packages/core/types/src/types/__tests__/utils/array.test.ts @@ -0,0 +1,85 @@ +import path from 'path'; +import { AssertTypeSelector, t } from 'ts-zen'; + +import { createTypeSelector } from '../test.utils'; + +const DEFINITIONS_PATH = path.join('utils', 'array.d.ts'); + +let type: AssertTypeSelector; + +describe('Utils.Array', () => { + beforeAll(() => { + type = createTypeSelector(DEFINITIONS_PATH); + }); + + test('String Values', () => { + type('StringValues').isUnion([ + t.stringLiteral('foo'), + t.stringLiteral('bar'), + t.stringLiteral('baz'), + ]); + }); + + test('Mixed Values', () => { + const expectedResultType = [ + t.anonymousObject({ + properties: { + foo: t.stringLiteral('bar'), + baz: t.booleanLiteral(false), + prop: t.anonymousObject({ + properties: { + foo: t.stringLiteral('bar'), + bar: t.stringLiteral('foo'), + }, + }), + }, + }), + t.numberLiteral(1), + t.stringLiteral('foo'), + t.booleanLiteral(true), + ]; + type('MixedValues').isUnion(expectedResultType); + // The result type should not contain the type 'never' + type('ContainsNever').isUnion(expectedResultType); + }); + + test('Number Values', () => { + type('NumberValues').isUnion([t.numberLiteral(1), t.numberLiteral(2), t.numberLiteral(3)]); + }); + + test('Bool Values', () => { + type('BoolValues').isBoolean(); + type('TrueBoolLiteralValues').isBooleanLiteral(true); + type('FalseBoolLiteralValues').isBooleanLiteral(false); + }); + + test('Object Values', () => { + type('ObjectValues').isUnion([ + t.anonymousObject({ + properties: { prop1: t.booleanLiteral(true), prop2: t.booleanLiteral(false) }, + }), + t.anonymousObject({ + properties: { + foo: t.stringLiteral('bar'), + baz: t.booleanLiteral(false), + prop: t.anonymousObject({ + properties: { + foo: t.stringLiteral('bar'), + bar: t.stringLiteral('foo'), + }, + }), + }, + }), + ]); + }); + + test('Is Empty', () => { + type('IsEmptyWithEmptyTuple').isBooleanLiteral(true); + type('IsEmptyWithNotEmptyTuple').isBooleanLiteral(false); + }); + + test('Is Not Empty', () => { + type('IsNotEmptyWithNotEmptyTuple').isBooleanLiteral(true); + type('IsNotEmptyWithEmptyTuple').isBooleanLiteral(false); + }); +}); diff --git a/packages/core/types/src/types/__tests__/utils/expression.test.ts b/packages/core/types/src/types/__tests__/utils/expression.test.ts new file mode 100644 index 0000000000..7bb5b61b60 --- /dev/null +++ b/packages/core/types/src/types/__tests__/utils/expression.test.ts @@ -0,0 +1,192 @@ +import path from 'path'; +import { t, AssertTypeSelector } from 'ts-zen'; + +import { createTypeSelector } from '../test.utils'; + +const DEFINITIONS_PATH = path.join('utils', 'expression.d.ts'); + +let type: AssertTypeSelector; + +describe('Utils.Expression', () => { + beforeAll(() => { + type = createTypeSelector(DEFINITIONS_PATH); + }); + + test('Is Never', () => { + type('IsNeverGivenNever').isBooleanLiteral(true); + type('IsNeverNotGivenNever').isBooleanLiteral(false); + type('IsNeverGivenUnknown').isBooleanLiteral(false); + }); + + test('Is Not Never', () => { + type('IsNotNeverGivenNever').isBooleanLiteral(false); + type('IsNotNeverGivenUnknown').isBooleanLiteral(true); + type('IsNotNeverGivenString').isBooleanLiteral(true); + type('IsNotNeverGivenStringLiteral').isBooleanLiteral(true); + }); + + test('Is True', () => { + type('IsTrueGivenTrue').isBooleanLiteral(true); + type('IsTrueGivenFalse').isBooleanLiteral(false); + type('IsTrueGivenBoolean').isBooleanLiteral(false); + type('IsTrueGivenNonBoolean').isBooleanLiteral(false); + type('IsTrueGivenNonBooleanLiteral').isBooleanLiteral(false); + type('IsTrueGivenOne').isBooleanLiteral(false); + type('IsTrueGivenZero').isBooleanLiteral(false); + }); + + test('Is False', () => { + type('IsFalseGivenFalse').isBooleanLiteral(true); + type('IsFalseGivenTrue').isBooleanLiteral(false); + type('IsFalseGivenBoolean').isBooleanLiteral(false); + type('IsFalseGivenNonBoolean').isBooleanLiteral(false); + type('IsFalseGivenNonBooleanLiteral').isBooleanLiteral(false); + type('IsFalseGivenOne').isBooleanLiteral(false); + type('IsFalseGivenZero').isBooleanLiteral(false); + }); + + test('Is Strict Equal', () => { + type('IsStrictEqualGivenNever').isBooleanLiteral(true); + type('IsStrictEqualGivenNeverAndUnknown').isBooleanLiteral(false); + type('IsStrictEqualGivenEqualLiterals').isBooleanLiteral(true); + type('IsStrictEqualGivenEqualTypes').isBooleanLiteral(true); + type('IsStrictEqualGivenDifferentLiterals').isBooleanLiteral(false); + type('IsStrictEqualGivenDifferentTypes').isBooleanLiteral(false); + type('IsStrictEqualGivenStringAndStringLiteral').isBooleanLiteral(false); + type('IsStrictEqualGivenStringLiteralAndString').isBooleanLiteral(false); + type('IsStrictEqualGivenNumberAndNumberLiteral').isBooleanLiteral(false); + type('IsStrictEqualGivenNumberLiteralAndNumber').isBooleanLiteral(false); + }); + + test('Extends', () => { + // String + type('StringExtendsString').isBooleanLiteral(true); + type('StringLiteralExtendsString').isBooleanLiteral(true); + type('StringExtendsStringLiteral').isBooleanLiteral(false); + type('StringExtendsNumber').isBooleanLiteral(false); + type('StringLiteralExtendsNumber').isBooleanLiteral(false); + type('StringExtendsNumberLiteral').isBooleanLiteral(false); + + // Number + type('NumberExtendsNumber').isBooleanLiteral(true); + type('NumberLiteralExtendsNumber').isBooleanLiteral(true); + type('NumberExtendsNumberLiteral').isBooleanLiteral(false); + type('NumberLiteralExtendsString').isBooleanLiteral(false); + type('NumberExtendsStringLiteral').isBooleanLiteral(false); + + // Object + type('ObjectExtendsObject').isBooleanLiteral(true); + type('ObjectLiteralExtendsObject').isBooleanLiteral(true); + type('ObjectExtendsObjectLiteral').isBooleanLiteral(false); + type('ObjectExtendsNumber').isBooleanLiteral(false); + type('ObjectExtendsAny').isBooleanLiteral(true); + type('ObjectExtendsUnknown').isBooleanLiteral(true); + type('ObjectExtendsNever').isBooleanLiteral(false); + + // Array + type('ArrayExtendsArray').isBooleanLiteral(true); + type('TupleExtendsArray').isBooleanLiteral(true); + type('StringArrayExtendsArray').isBooleanLiteral(true); + }); + + test('Not Extends', () => { + type('StringNotExtendsString').isBooleanLiteral(false); + type('StringLiteralNotExtendsString').isBooleanLiteral(false); + type('StringNotExtendsStringLiteral').isBooleanLiteral(true); + type('StringNotExtendsNumber').isBooleanLiteral(true); + type('StringLiteralNotExtendsNumber').isBooleanLiteral(true); + type('StringNotExtendsNumberLiteral').isBooleanLiteral(true); + type('NumberNotExtendsNumber').isBooleanLiteral(false); + type('NumberLiteralNotExtendsNumber').isBooleanLiteral(false); + type('NumberNotExtendsNumberLiteral').isBooleanLiteral(true); + type('NumberNotExtendsString').isBooleanLiteral(true); + type('NumberLiteralNotExtendsString').isBooleanLiteral(true); + type('NumberNotExtendsStringLiteral').isBooleanLiteral(true); + type('ObjectNotExtendsObject').isBooleanLiteral(false); + type('ObjectLiteralNotExtendsObject').isBooleanLiteral(false); + type('ObjectNotExtendsObjectLiteral').isBooleanLiteral(true); + type('ObjectNotExtendsNumber').isBooleanLiteral(true); + type('ObjectNotExtendsAny').isBooleanLiteral(false); + type('ObjectNotExtendsUnknown').isBooleanLiteral(false); + type('ObjectNotExtendsNever').isBooleanLiteral(true); + type('ArrayNotExtendsArray').isBooleanLiteral(false); + type('TupleNotExtendsArray').isBooleanLiteral(false); + type('StringArrayNotExtendsArray').isBooleanLiteral(false); + }); + + test('If', () => { + type('IfTrue').isBooleanLiteral(true); + type('IfFalse').isBooleanLiteral(false); + type('IfBoolean').isBooleanLiteral(false); + type('IfNumber').isBooleanLiteral(false); + type('IfString').isBooleanLiteral(false); + type('IfObject').isBooleanLiteral(false); + type('IfUnknown').isBooleanLiteral(false); + type('IfAny').isBooleanLiteral(true); + type('IfNever').isBooleanLiteral(true); + type('IfStringLiteral').isBooleanLiteral(false); + type('IfTuple').isBooleanLiteral(false); + type('IfArray').isBooleanLiteral(false); + type('IfStringArray').isBooleanLiteral(false); + type('IfTupleArray').isBooleanLiteral(false); + type('IfUnion').isBooleanLiteral(false); + type('IfIntersection').isBooleanLiteral(true); + type('IfFunction').isBooleanLiteral(false); + type('IfClass').isBooleanLiteral(false); + type('IfVoid').isBooleanLiteral(false); + type('IfNull').isBooleanLiteral(false); + type('IfUndefined').isBooleanLiteral(false); + type('IfWithStringReturnType').isStringLiteral('test'); + type('IfWithNumberReturnType').isNumberLiteral(1); + type('IfWithBooleanReturnType').isBooleanLiteral(true); + type('IfWithObjectReturnType').isAnonymousObject({ + properties: { foo: t.numberLiteral(1) }, + }); + type('IfWithTupleReturnType').isTuple([ + t.numberLiteral(1), + t.numberLiteral(2), + t.numberLiteral(3), + ]); + type('IfWithArrayReturnType').isArray(t.string()); + type('IfWithUnionReturnType').isUnion([t.string(), t.number()]); + type('IfWithVoidReturnType').isVoid(); + type('IfWithNullReturnType').isNull(); + type('IfWithUndefinedReturnType').isUndefined(); + type('IfWithNeverReturnType').isNever(); + type('IfWithUnknownReturnType').isUnknown(); + type('IfWithAnyReturnType').isAny(); + }); + + test('MatchFirst', () => { + type('MatchFirstReturnsTestSuccessful').isStringLiteral('test-successful'); + type('MatchFirstReturnsDefault').isStringLiteral('default'); + type('MatchFirstReturnsNeverWithEmptyTests').isNever(); + type('MatchFirstReturnsNeverWithNeverDefault').isNever(); + }); + + test('MatchAllIntersect', () => { + type('MatchAllIntersectWithOneTrueCondition').isAnonymousObject({ + properties: { + test: t.numberLiteral(1), + }, + }); + type('MatchAllIntersectWithAllFalseConditions').isUnknown(); + type('MatchAllIntersectWithIntersection').isStringLiteral('test'); + }); + + test('Test', () => { + type('TestPasses').isTuple([t.booleanLiteral(true), t.stringLiteral('test')]); + type('TestFails').isTuple([t.booleanLiteral(false), t.stringLiteral('test')]); + }); + + test('And', () => { + type('AndTrue').isBooleanLiteral(true); + type('AndFalse').isBooleanLiteral(false); + }); + + test('Or', () => { + type('OrTrue').isBooleanLiteral(true); + type('OrFalse').isBooleanLiteral(false); + type('OrTrueFalse').isBooleanLiteral(true); + }); +}); diff --git a/packages/core/types/src/types/__tests__/utils/guard.test.ts b/packages/core/types/src/types/__tests__/utils/guard.test.ts new file mode 100644 index 0000000000..6e1d700608 --- /dev/null +++ b/packages/core/types/src/types/__tests__/utils/guard.test.ts @@ -0,0 +1,52 @@ +import path from 'path'; +import { AssertTypeSelector, t } from 'ts-zen'; + +import { createTypeSelector } from '../test.utils'; + +const DEFINITIONS_PATH = path.join('utils', 'guard.d.ts'); + +let type: AssertTypeSelector; + +describe('Utils.Guard', () => { + beforeAll(() => { + type = createTypeSelector(DEFINITIONS_PATH); + }); + + test('Never Guard', () => { + type('NeverGuardGetsNeverWithDefaultFallback').isUnknown(); + type('NeverGuardGetsNeverWithCustomFallback').isString(); + type('NeverGuardGetsAny').isAny(); + type('NeverGuardGetsNull').isNull(); + type('NeverGuardGetsUndefined').isUndefined(); + type('NeverGuardGetsUnknown').isUnknown(); + }); + + describe('OfTypes', () => { + test('Single Type', () => { + type('OfTypesNeverGetsNeverWithFallback').isString(); + type('OfTypesNeverGetsNeverWithoutFallback').isUnknown(); + + type('OfTypesUndefined').isUnknown(); + type('OfTypesUndefinedGetsString').isString(); + + type('OfTypesNull').isUnknown(); + type('OfTypesNullGetsString').isString(); + + type('OfTypesUnknown').isNull(); + type('OfTypesUnknownGetString').isString(); + + type('OfTypesAnyGetsAny').isUnknown(); + type('OfTypesAnyGetsString').isUnknown(); + + type('OfTypeUnionGetsMatchingUnion').isUnknown(); + type('OfTypeUnionGetsUnionElement').isString(); + }); + + test('Multiple Type Guard', () => { + type('OfTypesStringAndNumberGetsString').isUnknown(); + type('OfTypesStringAndNumberGetsNumber').isUnknown(); + type('OfTypesStringAndNumberGetsUnionOfStringNumber').isUnion([t.string(), t.number()]); + type('OfTypesStringAndNumberGetsBoolean').isBoolean(); + }); + }); +}); diff --git a/packages/core/types/src/types/__tests__/utils/object.test.ts b/packages/core/types/src/types/__tests__/utils/object.test.ts new file mode 100644 index 0000000000..d2cb249368 --- /dev/null +++ b/packages/core/types/src/types/__tests__/utils/object.test.ts @@ -0,0 +1,74 @@ +import path from 'path'; +import { t, AssertTypeSelector } from 'ts-zen'; +import type ObjectUtils from '../definitions/utils/object'; +import { createTypeSelector } from '../test.utils'; + +const DEFINITIONS_PATH = path.join('utils', 'object.d.ts'); + +let type: AssertTypeSelector; + +describe('Utils.Object', () => { + beforeAll(() => { + type = createTypeSelector(DEFINITIONS_PATH); + }); + + test('KeysBy', () => { + type('KeysByString').isUnion([t.stringLiteral('foo'), t.stringLiteral('bar')]); + type('KeysByNumber').isStringLiteral('foobar'); + type('KeysByNever').isNever(); + type('KeysByUnknown').isUnion([ + t.stringLiteral('foo'), + t.stringLiteral('bar'), + t.stringLiteral('foobar'), + ]); + type('KeysByObj').isUnion([t.stringLiteral('foo'), t.stringLiteral('bar')]); + }); + + test('KeysExcept', () => { + type('KeysExceptString').isStringLiteral('foobar'); + type('KeysExceptNumber').isUnion([t.stringLiteral('foo'), t.stringLiteral('bar')]); + type('KeysExceptNever').isUnion([ + t.stringLiteral('foo'), + t.stringLiteral('bar'), + t.stringLiteral('foobar'), + ]); + type('KeysExceptUnknown').isNever(); + type('KeysExceptObj').isStringLiteral('other'); + }); + + test('PickBy', () => { + type('PickByString').isMappedType({ + properties: { + foo: t.stringLiteral('bar'), + bar: t.stringLiteral('foo'), + }, + }); + type('PickByNumber').isMappedType({ + properties: { + foobar: t.numberLiteral(2), + }, + }); + type('PickByNever').isMappedType({ + properties: {}, + }); + type('PickByUnknown').isMappedType({ + properties: { + foobar: t.numberLiteral(2), + foo: t.stringLiteral('bar'), + bar: t.stringLiteral('foo'), + }, + }); + type('PickByObj').isMappedType({ + properties: { + foo: t.mappedType({ properties: { x: t.stringLiteral('bar') } }), + bar: t.mappedType({ properties: { x: t.stringLiteral('foo') } }), + }, + }); + }); + + test('Values', () => { + type('Values').isUnion([t.stringLiteral('foo'), t.stringLiteral('bar'), t.numberLiteral(2)]); + type('ValuesNever').isNever(); + type('ValuesContainNever').isUnion([t.stringLiteral('foo'), t.stringLiteral('bar')]); + }); +}); diff --git a/packages/core/types/src/types/__tests__/utils/string.test.ts b/packages/core/types/src/types/__tests__/utils/string.test.ts index b76eacda23..0aa066edfb 100644 --- a/packages/core/types/src/types/__tests__/utils/string.test.ts +++ b/packages/core/types/src/types/__tests__/utils/string.test.ts @@ -1,65 +1,73 @@ import path from 'path'; -import { fromFile, t, AssertTypeSelector } from 'ts-zen'; -const STRING_UTILS_DTS_PATH = path.join(__dirname, '..', 'definitions', 'utils', 'string.d.ts'); +import { AssertTypeSelector, t } from 'ts-zen'; -let assertType: AssertTypeSelector; +import { createTypeSelector } from '../test.utils'; +import type StringUtils from '../definitions/utils/string'; + +const DEFINITIONS_PATH = path.join('utils', 'string.d.ts'); + +let type: AssertTypeSelector; describe('Utils.String', () => { beforeAll(() => { - assertType = fromFile(STRING_UTILS_DTS_PATH, { - compilerOptions: { strict: true }, - ignoreProjectOptions: true, - }); + type = createTypeSelector(DEFINITIONS_PATH); }); test('Dict', () => { - // TODO: Replace with isMappedType matcher when available - assertType('NumberDict').equals('{ [x: string]: number; }'); - assertType('StringDict').equals('{ [x: string]: string; }'); - assertType('BooleanDict').equals('{ [x: string]: boolean; }'); + type('NumberDict').isAnonymousObject({ + indexes: [{ keyType: t.string(), type: t.number() }], + }); + + type('StringDict').isAnonymousObject({ + indexes: [{ keyType: t.string(), type: t.string() }], + }); + + type('BooleanDict').isAnonymousObject({ + indexes: [{ keyType: t.string(), type: t.boolean() }], + }); }); test('EndsWith', () => { - assertType('EndsWithCorrectNumber').isBooleanLiteral(true); - assertType('EndsWithIncorrectNumber').isBooleanLiteral(false); - assertType('EndsWithCorrectString').isBooleanLiteral(true); - assertType('EndsWithIncorrectString').isBooleanLiteral(false); + type('EndsWithCorrectNumber').isBooleanLiteral(true); + type('EndsWithIncorrectNumber').isBooleanLiteral(false); + type('EndsWithCorrectString').isBooleanLiteral(true); + type('EndsWithIncorrectString').isBooleanLiteral(false); }); test('StartsWith', () => { - assertType('StartsWithCorrectNumber').isBooleanLiteral(true); - assertType('StartsWithIncorrectNumber').isBooleanLiteral(false); - assertType('StartsWithCorrectString').isBooleanLiteral(true); - assertType('StartsWithIncorrectString').isBooleanLiteral(false); + type('StartsWithCorrectNumber').isBooleanLiteral(true); + type('StartsWithIncorrectNumber').isBooleanLiteral(false); + type('StartsWithCorrectString').isBooleanLiteral(true); + type('StartsWithIncorrectString').isBooleanLiteral(false); }); test('Includes', () => { const template = (str: string | number | boolean) => [t.string(), String(str), t.string()]; - assertType('IncludesNumber').isTemplateLiteral(template(42)); - assertType('IncludesString').isTemplateLiteral(template('foo')); - assertType('IncludesBoolean').isUnion([ + type('IncludesNumber').isTemplateLiteral(template(42)); + type('IncludesString').isTemplateLiteral(template('foo')); + type('IncludesBoolean').isUnion([ t.templateLiteral(template(true)), t.templateLiteral(template(false)), ]); - assertType('IncludesBooleanLiteral').isTemplateLiteral(template(true)); + type('IncludesBooleanLiteral').isTemplateLiteral(template(true)); }); test('NonEmpty', () => { - assertType('NonEmptyOnEmptyString').isNever(); - assertType('NonEmptyOnNonEmptyString').isStringLiteral('Hello World'); + type('NonEmptyOnEmptyString').isNever(); + type('NonEmptyOnNonEmptyString').isStringLiteral('Hello World'); }); test('Prefix', () => { - assertType('PrefixEmptyString').isStringLiteral('Hello'); - assertType('PrefixString').isTemplateLiteral(['Hello ', t.string()]); - assertType('PrefixLiteralString').isStringLiteral('Hello World'); - assertType('PrefixLiteralStringUnion').isUnion([ + type('PrefixEmptyString').isStringLiteral('Hello'); + type('PrefixString').isTemplateLiteral(['Hello ', t.string()]); + type('PrefixLiteralString').isStringLiteral('Hello World'); + type('PrefixLiteralStringUnion').isUnion([ t.stringLiteral('Hello World'), t.stringLiteral('Hello Everyone'), ]); - assertType('PrefixLiteralStringWithUnion').isUnion([ + type('PrefixLiteralStringWithUnion').isUnion([ t.stringLiteral('Hello World'), t.stringLiteral('Bonjour World'), t.stringLiteral('Hola World'), @@ -67,33 +75,31 @@ describe('Utils.String', () => { }); test('Suffix', () => { - assertType('SuffixEmptyString').isStringLiteral('Hello'); - assertType('SuffixString').isTemplateLiteral([t.string(), '.']); - assertType('SuffixLiteralString').isStringLiteral('Hello World'); - assertType('SuffixLiteralStringUnion').isUnion([ + type('SuffixEmptyString').isStringLiteral('Hello'); + type('SuffixString').isTemplateLiteral([t.string(), '.']); + type('SuffixLiteralString').isStringLiteral('Hello World'); + type('SuffixLiteralStringUnion').isUnion([ t.stringLiteral('Hello World'), t.stringLiteral('Bonjour World'), t.stringLiteral('Hola World'), ]); - assertType('SuffixLiteralStringWithUnion').isUnion([ + type('SuffixLiteralStringWithUnion').isUnion([ t.stringLiteral('Hello World'), t.stringLiteral('Hello Everyone'), ]); }); test('Literal', () => { - assertType('Literal').isUnion([t.string(), t.number(), t.bigInt(), t.booleanLiteral()]); + type('Literal').isUnion([t.string(), t.number(), t.bigInt(), t.booleanLiteral()]); }); test('Split', () => { - assertType('SplitEmptyStringBySpace').isTuple([]); - assertType('SplitEmptyStringByEmptyString').isTuple([]); - assertType('SplitEmptyStringByString').isTuple([]); - assertType('SplitBySpace').isTuple( - ['Hello', 'World,', 'How', 'are', 'you?'].map(t.stringLiteral) - ); - assertType('SplitByEmptyString').isTuple(['H', 'e', 'l', 'l', 'o'].map(t.stringLiteral)); + type('SplitEmptyStringBySpace').isTuple([]); + type('SplitEmptyStringByEmptyString').isTuple([]); + type('SplitEmptyStringByString').isTuple([]); + type('SplitBySpace').isTuple(['Hello', 'World,', 'How', 'are', 'you?'].map(t.stringLiteral)); + type('SplitByEmptyString').isTuple(['H', 'e', 'l', 'l', 'o'].map(t.stringLiteral)); // This will use any string character as a delimiter, thus removing 1/2 characters - assertType('SplitByString').isTuple(['H', 'l', 'o'].map(t.stringLiteral)); + type('SplitByString').isTuple(['H', 'l', 'o'].map(t.stringLiteral)); }); }); diff --git a/packages/core/types/src/types/utils/string.ts b/packages/core/types/src/types/utils/string.ts index db5af16ced..f1cfbec38c 100644 --- a/packages/core/types/src/types/utils/string.ts +++ b/packages/core/types/src/types/utils/string.ts @@ -38,9 +38,9 @@ export type Suffix = `${TValue}$ export type Prefix = `${TPrefix}${TValue}`; /** - * Creates a record where every key is a string and every value is `T` + * Creates an indexed object where every key is a string and every value is `T` */ -export type Dict = Record; +export type Dict = { [key: string]: T }; /** * Checks if a given string ends with the given literal diff --git a/yarn.lock b/yarn.lock index dcf80262aa..e9b5b5253c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7834,6 +7834,7 @@ __metadata: semver: 7.5.4 statuses: 2.0.1 supertest: 6.3.3 + ts-zen: "https://github.com/strapi/ts-zen#66e02232f5997674cc7032ea3ee59d9864863732" tsconfig: 4.13.7 typescript: 5.2.2 vite: 4.4.9