Skip to content

Commit

Permalink
fix: custom ts3.4 downlevel for transform/type-transform
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe committed Jul 25, 2023
1 parent 3502553 commit f488dac
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/shiny-starfishes-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/types": patch
---

custom ts3.4 downlevel for types/transform/type-transform
2 changes: 1 addition & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:es": "tsc -p tsconfig.es.json",
"build:types": "tsc -p tsconfig.types.json",
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
"build:types:downlevel": "rimraf dist-types/ts3.4 && downlevel-dts dist-types dist-types/ts3.4 && node scripts/downlevel",
"stage-release": "rimraf ./.release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz",
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo",
"lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"",
Expand Down
11 changes: 11 additions & 0 deletions packages/types/scripts/downlevel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const fs = require("fs");
const path = require("path");

const pkgRoot = path.join(__dirname, "..");

function replaceDownlevelFile(pathFromSrc = "") {
const code = fs.readFileSync(path.join(pkgRoot, "dist-types", "ts3.4", "downlevel-ts3.4", pathFromSrc), "utf-8");
fs.writeFileSync(path.join(pkgRoot, "dist-types", "ts3.4", pathFromSrc), code, "utf-8");
}

replaceDownlevelFile("transform/type-transform.d.ts");
34 changes: 34 additions & 0 deletions packages/types/src/downlevel-ts3.4/transform/type-transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @public
*
* Transforms any members of the object T having type FromType
* to ToType. This applies only to exact type matches.
*
* This is for the case where FromType is a union and only those fields
* matching the same union should be transformed.
*/
export type Transform<T, FromType, ToType> = RecursiveTransformExact<T, FromType, ToType>;

/**
* @internal
*
* Returns ToType if T matches exactly with FromType.
*/
type TransformExact<T, FromType, ToType> = [T] extends [FromType] ? ([FromType] extends [T] ? ToType : T) : T;

/**
* @internal
*
* Applies TransformExact to members of an object recursively.
*/
type RecursiveTransformExact<T, FromType, ToType> = T extends Function
? T
: T extends object
? {
[key in keyof T]: [T[key]] extends [FromType]
? [FromType] extends [T[key]]
? ToType
: RecursiveTransformExact<T[key], FromType, ToType>
: RecursiveTransformExact<T[key], FromType, ToType>;
}
: TransformExact<T, FromType, ToType>;
24 changes: 19 additions & 5 deletions packages/types/src/transform/type-transform.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import type { Transform as DownlevelTransform } from "../downlevel-ts3.4/transform/type-transform";
import type { Transform } from "./type-transform";

type Exact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;

// It should transform exact unions recursively.
type A = {
a: string;
b: number | string;
c: boolean | number | string;
nested: A;
};

type T = Transform<A, number | string, "enum">;
{
// It should transform exact unions recursively.

const assert1: Exact<T["a"], string> = true as const;
const assert2: Exact<T["b"], "enum"> = true as const;
type T = Transform<A, number | string, "enum">;

const assert3: Exact<T["nested"]["nested"]["nested"]["b"], "enum"> = true as const;
const assert1: Exact<T["a"], string> = true as const;
const assert2: Exact<T["b"], "enum"> = true as const;

const assert3: Exact<T["nested"]["nested"]["nested"]["b"], "enum"> = true as const;
}

{
// the downlevel should function similarly
type T = DownlevelTransform<A, number | string, "enum">;

const assert1: Exact<T["a"], string> = true as const;
const assert2: Exact<T["b"], "enum"> = true as const;

const assert3: Exact<T["nested"]["nested"]["nested"]["b"], "enum"> = true as const;
}

0 comments on commit f488dac

Please # to comment.