From ea65665c8a7868c5307f23f1486babec48fcf0e7 Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Wed, 4 Oct 2023 23:24:35 +0100 Subject: [PATCH 1/6] feat: add new flow utils --- README.md | 8 ++--- package.json | 2 +- .../__snapshots__/spread.spec.ts.snap | 32 +++++++++++++++++-- .../__snapshots__/utility-types.spec.ts.snap | 31 +++++++++--------- src/__tests__/spread.spec.ts | 25 ++++++++++++++- src/__tests__/utility-types.spec.ts | 4 +++ src/printers/identifiers.ts | 24 ++++---------- src/printers/node.ts | 17 +++++----- yarn.lock | 14 ++++---- 9 files changed, 101 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 3bdbbdc8..14cec25e 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ It's surprisingly robust and non-lossy as it stands right now, in big part thank | ✅ | ReadonlySet | `ReadonlySet` | `$ReadOnlySet` | | ✅ | ReadonlyMap | `ReadonlyMap` | `$ReadOnlyMap` | | ✅ | Record | `Record` | `{ [key: K]: T }` | -| | Pick | `Pick` | | -| | Exclude | `Exclude` | | -| | Extract | `Extract` | | +| ✅ | Pick | `Pick` | `Pick` | +| ✅ | Exclude | `Exclude` | `Exclude` | +| ✅ | Extract | `Extract` | `Extract` | | ✅ | NonNullable | `NonNullable` | `$NonMaybeType` | | ✅ | ReturnType | `ReturnType` | `$Call<((...args: any[]) => R) => R, F>` | | | InstanceType | `InstanceType` | | -| | Required | `Required` | | +| ✅ | Required | `Required` | `Required` | | | ThisType | `ThisType` | | | ✅ | T['string'] | `T['string']` | `$PropertyType` | | ✅ | T[k] | `T[k]` | `$ElementType` | diff --git a/package.json b/package.json index a9483683..57ba4410 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "eslint-plugin-import": "^2.25.4", "eslint-plugin-jest": "^25.3.4", "eslint-plugin-prettier": "^4.0.0", - "flow-bin": "^0.195.0", + "flow-bin": "^0.217.2", "jest": "^27.4.7", "mongodb": "^4.1.3" }, diff --git a/src/__tests__/__snapshots__/spread.spec.ts.snap b/src/__tests__/__snapshots__/spread.spec.ts.snap index d2390247..9cdce0a0 100644 --- a/src/__tests__/__snapshots__/spread.spec.ts.snap +++ b/src/__tests__/__snapshots__/spread.spec.ts.snap @@ -7,7 +7,7 @@ declare var combination: Foo & Bar; " `; -exports[`should use spread when performing union of object types 1`] = ` +exports[`should not use spread when performing union of inexact object types 1`] = ` "declare type Foo = { foo: number, ... @@ -16,11 +16,37 @@ declare type Bar = { bar: string, ... }; -declare var combination: { ...Foo, ...Bar }; +declare var combination: Foo & Bar; +" +`; + +exports[`should not use spread when performing union of inexact object types 2`] = ` +"declare type Foo = { + foo: number, + ... +}; +declare type Bar = { + bar: string, + ... +}; +declare var combination: Foo & Bar; +" +`; + +exports[`should use spread when performing union of exact object types 1`] = ` +"declare type Foo = { + foo: number, + ... +}; +declare type Bar = { + bar: string, + ... +}; +declare var combination: Foo & Bar; " `; -exports[`should use spread when performing union of object types 2`] = ` +exports[`should use spread when performing union of exact object types 2`] = ` "declare type Foo = {| foo: number, |}; diff --git a/src/__tests__/__snapshots__/utility-types.spec.ts.snap b/src/__tests__/__snapshots__/utility-types.spec.ts.snap index b79e909a..91b555fd 100644 --- a/src/__tests__/__snapshots__/utility-types.spec.ts.snap +++ b/src/__tests__/__snapshots__/utility-types.spec.ts.snap @@ -1,21 +1,21 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should handle Omit type 1`] = ` -"declare type A = $Diff< +"declare type A = Omit< { a: string, b: number, ... }, - { a: any } + \\"a\\" >; -declare type B = $Diff< +declare type B = Omit< { a: string, b: number, ... }, - { a: any, b: any } + \\"a\\" | \\"b\\" >; declare type O = { a: string, @@ -23,7 +23,7 @@ declare type O = { ... }; declare type U = \\"a\\"; -declare type C = $Diff; +declare type C = Omit; " `; @@ -32,19 +32,20 @@ exports[`should handle utility types 1`] = ` a: number, ... }>; -declare type B = $Rest< - { - a: number, - ... - }, - { ... } ->; +declare type B = Partial<{ + a: number, + ... +}>; declare type C = $NonMaybeType; declare type D = $ReadOnlyArray; -declare type E = $Call<((...args: any[]) => R) => R, () => string>; +declare type E = ReturnType<() => string>; declare type F = { [key: string]: number, ... }; declare type G = $ReadOnlySet; declare type H = $ReadOnlyMap; +declare type I = Pick; +declare type J = Exclude<1 | 2 | 3 | 4, 1 | 3>; +declare type K = Extract; +declare type L = Required; declare type A1 = Readonly; declare type B1 = Partial; declare type C1 = NonNullable; @@ -52,10 +53,10 @@ declare type D1 = ReadonlyArray; declare type E1 = ReturnType; declare type F1 = Record; declare type A2 = $ReadOnly; -declare type B2 = $Rest; +declare type B2 = Partial; declare type C2 = $NonMaybeType; declare type D2 = $ReadOnlyArray; -declare type E2 = $Call<((...args: any[]) => R) => R, () => T>; +declare type E2 = ReturnType<() => T>; declare type F2 = { [key: T]: U, ... }; " `; diff --git a/src/__tests__/spread.spec.ts b/src/__tests__/spread.spec.ts index 9d1f6223..8764559f 100644 --- a/src/__tests__/spread.spec.ts +++ b/src/__tests__/spread.spec.ts @@ -1,7 +1,7 @@ import { compiler, beautify } from ".."; import "../test-matchers"; -it("should use spread when performing union of object types", () => { +it("should use spread when performing union of exact object types", () => { const ts = ` type Foo = { foo: number }; type Bar = { bar: string }; @@ -24,6 +24,29 @@ const combination: Foo & Bar; } }); +it("should not use spread when performing union of inexact object types", () => { + const ts = ` +type Foo = { foo: number }; +type Bar = { bar: string }; +const combination: Foo & Bar; +`; + + { + const result = compiler.compileDefinitionString(ts, { quiet: true }); + expect(beautify(result)).toMatchSnapshot(); + expect(result).toBeValidFlowTypeDeclarations(); + } + + { + const result = compiler.compileDefinitionString(ts, { + quiet: true, + inexact: true, + }); + expect(beautify(result)).toMatchSnapshot(); + expect(result).toBeValidFlowTypeDeclarations(); + } +}); + it("should not insert spread when performing union of class types", () => { const ts = ` class Foo {} diff --git a/src/__tests__/utility-types.spec.ts b/src/__tests__/utility-types.spec.ts index c275f599..8b5d211b 100644 --- a/src/__tests__/utility-types.spec.ts +++ b/src/__tests__/utility-types.spec.ts @@ -11,6 +11,10 @@ type E = ReturnType<() => string> type F = Record type G = ReadonlySet type H = ReadonlyMap +type I = Pick +type J = Exclude<1 | 2 | 3 | 4, 1 | 3> +type K = Extract +type L = Required type A1 = Readonly type B1 = Partial diff --git a/src/printers/identifiers.ts b/src/printers/identifiers.ts index d967ceb4..2156617e 100644 --- a/src/printers/identifiers.ts +++ b/src/printers/identifiers.ts @@ -38,24 +38,14 @@ const identifiers: { [name: string]: IdentifierResult } = { Readonly: "$ReadOnly", RegExpMatchArray: "RegExp$matchResult", NonNullable: "$NonMaybeType", - Partial: ([type]: any[]) => { - const isInexact = opts().inexact; - return `$Rest<${printers.node.printType(type)}, {${ - isInexact ? "..." : "" - }}>`; - }, - ReturnType: (typeArguments: any[]) => { - return `$Call<((...args: any[]) => R) => R, ${printers.node.printType( - typeArguments[0], - )}>`; - }, + Pick: "Pick", + Exclude: "Exclude", + Extract: "Extract", + Required: "Required", + Partial: "Partial", + ReturnType: "ReturnType", Record, - Omit: ([obj, keys]: [any, any]) => { - return `$Diff<${printers.node.printType(obj)},${Record( - [keys, { kind: ts.SyntaxKind.AnyKeyword }], - false, - )}>`; - }, + Omit: "Omit", }; export const print = withEnv((env, kind) => { diff --git a/src/printers/node.ts b/src/printers/node.ts index e83a9bf3..ed995391 100644 --- a/src/printers/node.ts +++ b/src/printers/node.ts @@ -756,29 +756,30 @@ export const printType = withEnv( return ""; case ts.SyntaxKind.IntersectionType: { - // for non-class types, we can't easily just merge types together using & - // this is because in Typescript + // for exact types, we can't easily just merge types together + // using &. This is because in Typescript // { a: number } & { b: string} // is NOT equivalent to {| a: number |} & {| b: string |} in Flow // since you can't intersect exact types in Flow - // https://github.com/facebook/flow/issues/4946#issuecomment-331520118 + // https://github.com/joarwilk/flowgen/pull/136 // instead, you have to use the spread notation - // HOWEVER, you must use & to intersect classes (you can't spread a class) const containsClass = type.types .map(checker.current.getTypeAtLocation) .find(type => type.isClass()); - if (containsClass) { + const isInexact = opts().inexact; + + // Classes and inexact objects + if (isInexact || containsClass) { return type.types.map(printType).join(" & "); } + // Exact objects should use spread instead const spreadType = type.types .map(type => `...${printType(type)}`) .join(","); - const isInexact = opts().inexact; - - return isInexact ? `{ ${spreadType} }` : `{| ${spreadType} |}`; + return `{| ${spreadType} |}`; } case ts.SyntaxKind.MethodDeclaration: diff --git a/yarn.lock b/yarn.lock index 5f13bcca..b0049e43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2082,9 +2082,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001286: - version "1.0.30001296" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz#d99f0f3bee66544800b93d261c4be55a35f1cec8" - integrity sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q== + version "1.0.30001543" + resolved "https://npm.abs.sh/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz" + integrity sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA== chalk@^2.0.0: version "2.4.2" @@ -2755,10 +2755,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== -flow-bin@^0.195.0: - version "0.195.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.195.0.tgz#67075596cc4ef2560ec001d5c781b07777f05f81" - integrity sha512-VGIwDVxcZRLbc2k8dsMcdHHjrPDzr1frqGvpRdYpdnpK/qi4heHFGDU747NElcsNiqyzs+G8gaZmhxZiBvwyUg== +flow-bin@^0.217.2: + version "0.217.2" + resolved "https://npm.abs.sh/flow-bin/-/flow-bin-0.217.2.tgz#96affa17f3cb303019f740bffeb28cfab7ce1250" + integrity sha512-fk4NcfybYjzlww1sEsfk71nqXvonAYpMRFEjmZxibDWWBiaw8DGmqXWZ7XzSunVB15VkJfOstn/sYP1EYPPyWg== form-data@^3.0.0: version "3.0.1" From 8c4db6309803f55c8fd27e0b771a322c9702a4cf Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Wed, 4 Oct 2023 23:29:34 +0100 Subject: [PATCH 2/6] fix: snaps --- .../__snapshots__/spread.spec.ts.snap | 26 ------------ src/__tests__/spread.spec.ts | 42 ++++++------------- 2 files changed, 12 insertions(+), 56 deletions(-) diff --git a/src/__tests__/__snapshots__/spread.spec.ts.snap b/src/__tests__/__snapshots__/spread.spec.ts.snap index 9cdce0a0..002a9357 100644 --- a/src/__tests__/__snapshots__/spread.spec.ts.snap +++ b/src/__tests__/__snapshots__/spread.spec.ts.snap @@ -20,33 +20,7 @@ declare var combination: Foo & Bar; " `; -exports[`should not use spread when performing union of inexact object types 2`] = ` -"declare type Foo = { - foo: number, - ... -}; -declare type Bar = { - bar: string, - ... -}; -declare var combination: Foo & Bar; -" -`; - exports[`should use spread when performing union of exact object types 1`] = ` -"declare type Foo = { - foo: number, - ... -}; -declare type Bar = { - bar: string, - ... -}; -declare var combination: Foo & Bar; -" -`; - -exports[`should use spread when performing union of exact object types 2`] = ` "declare type Foo = {| foo: number, |}; diff --git a/src/__tests__/spread.spec.ts b/src/__tests__/spread.spec.ts index 8764559f..a80028f7 100644 --- a/src/__tests__/spread.spec.ts +++ b/src/__tests__/spread.spec.ts @@ -7,21 +7,12 @@ type Foo = { foo: number }; type Bar = { bar: string }; const combination: Foo & Bar; `; - - { - const result = compiler.compileDefinitionString(ts, { quiet: true }); - expect(beautify(result)).toMatchSnapshot(); - expect(result).toBeValidFlowTypeDeclarations(); - } - - { - const result = compiler.compileDefinitionString(ts, { - quiet: true, - inexact: false, - }); - expect(beautify(result)).toMatchSnapshot(); - expect(result).toBeValidFlowTypeDeclarations(); - } + const result = compiler.compileDefinitionString(ts, { + quiet: true, + inexact: false, + }); + expect(beautify(result)).toMatchSnapshot(); + expect(result).toBeValidFlowTypeDeclarations(); }); it("should not use spread when performing union of inexact object types", () => { @@ -30,21 +21,12 @@ type Foo = { foo: number }; type Bar = { bar: string }; const combination: Foo & Bar; `; - - { - const result = compiler.compileDefinitionString(ts, { quiet: true }); - expect(beautify(result)).toMatchSnapshot(); - expect(result).toBeValidFlowTypeDeclarations(); - } - - { - const result = compiler.compileDefinitionString(ts, { - quiet: true, - inexact: true, - }); - expect(beautify(result)).toMatchSnapshot(); - expect(result).toBeValidFlowTypeDeclarations(); - } + const result = compiler.compileDefinitionString(ts, { + quiet: true, + inexact: true, + }); + expect(beautify(result)).toMatchSnapshot(); + expect(result).toBeValidFlowTypeDeclarations(); }); it("should not insert spread when performing union of class types", () => { From 5103e864cfccf40a445348e991d2aa7f097e1f56 Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Wed, 4 Oct 2023 23:36:42 +0100 Subject: [PATCH 3/6] chore: update comment --- src/printers/node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printers/node.ts b/src/printers/node.ts index ed995391..7a016ac8 100644 --- a/src/printers/node.ts +++ b/src/printers/node.ts @@ -756,7 +756,7 @@ export const printType = withEnv( return ""; case ts.SyntaxKind.IntersectionType: { - // for exact types, we can't easily just merge types together + // for exact types we can't easily just intersect types together // using &. This is because in Typescript // { a: number } & { b: string} // is NOT equivalent to {| a: number |} & {| b: string |} in Flow From e0ff65c09ef2b146b343ffdb4674d745fb2fb105 Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Wed, 4 Oct 2023 23:39:33 +0100 Subject: [PATCH 4/6] Update Readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14cec25e..4eb77754 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,9 @@ It's surprisingly robust and non-lossy as it stands right now, in big part thank | ✅ | Pick | `Pick` | `Pick` | | ✅ | Exclude | `Exclude` | `Exclude` | | ✅ | Extract | `Extract` | `Extract` | +| ✅ | Omit | `Omit` | `Omit` | | ✅ | NonNullable | `NonNullable` | `$NonMaybeType` | -| ✅ | ReturnType | `ReturnType` | `$Call<((...args: any[]) => R) => R, F>` | +| ✅ | ReturnType | `ReturnType` | `ReturnType` | | | InstanceType | `InstanceType` | | | ✅ | Required | `Required` | `Required` | | | ThisType | `ThisType` | | From 5454cf97115898a53b6be0ba0ce1f1142c0428d9 Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Thu, 5 Oct 2023 00:02:48 +0100 Subject: [PATCH 5/6] feat: add support for this --- README.md | 2 +- .../function-exports.spec.ts.snap | 19 +++++++++++++------ .../__snapshots__/interfaces.spec.ts.snap | 12 ++++++------ src/__tests__/function-exports.spec.ts | 12 ++++++++++-- src/__tests__/interfaces.spec.ts | 6 +++--- src/printers/function.ts | 8 ++------ src/printers/node.ts | 6 +----- 7 files changed, 36 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 4eb77754..07533d0a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ It's surprisingly robust and non-lossy as it stands right now, in big part thank | ✅ | Variance | `interface A { readonly b: B, c: C }` | `interface A { +b: B, c: C }` | | ✅ | Functions | `(a: A, b: B) => C` | `(a: A, b: B) => C` | | ✅ | Indexers | `{[k: string]: string}` | `{[k: string]: string}` | -| | This type | `(this: X, a: A, b: B) => C` | `(a: A, b: B) => C` | +| ✅ | This type | `(this: X, a: A, b: B) => C` | `(this: X, a: A, b: B) => C` | | | Type guards | `(a: X) => a is A` | `(a: X) => boolean` | | ✅ | Type parameter bounds | `function f(a:A){}` | `function f(a:A){}` | | ✅ | keyof X | `keyof X` | `$Keys` | diff --git a/src/__tests__/__snapshots__/function-exports.spec.ts.snap b/src/__tests__/__snapshots__/function-exports.spec.ts.snap index 21cef010..59a1f527 100644 --- a/src/__tests__/__snapshots__/function-exports.spec.ts.snap +++ b/src/__tests__/__snapshots__/function-exports.spec.ts.snap @@ -46,17 +46,24 @@ declare export function toString(b: string): void; " `; -exports[`should not break with Promise return types - issue 156 1`] = ` -"declare export var fn: () => Promise; +exports[`should keep default parameters in functions 1`] = ` +"declare function addClickListener(onclick: (e: Event) => void): T; " `; -exports[`should remove default parameters from functions 1`] = ` -"declare function addClickListener(onclick: (e: Event) => void): T; +exports[`should keep this annotation in functions 1`] = ` +"declare function addClickListener( + onclick: (this: void, e: Event) => void +): void; +" +`; + +exports[`should not break with Promise return types - issue 156 1`] = ` +"declare export var fn: () => Promise; " `; -exports[`should remove this annotation from functions 1`] = ` -"declare function addClickListener(onclick: (e: Event) => void): void; +exports[`should transform generic \`\` to \`\` on functions 1`] = ` +"declare function addClickListener(onclick: (e: Event) => void): T; " `; diff --git a/src/__tests__/__snapshots__/interfaces.spec.ts.snap b/src/__tests__/__snapshots__/interfaces.spec.ts.snap index a2c3e5be..89b283f7 100644 --- a/src/__tests__/__snapshots__/interfaces.spec.ts.snap +++ b/src/__tests__/__snapshots__/interfaces.spec.ts.snap @@ -139,23 +139,23 @@ exports[`should handle untyped object binding pattern 1`] = ` " `; -exports[`should remove generic defaults in call signature 1`] = ` +exports[`should keep generic defaults in call signature 1`] = ` "declare interface AbstractLevelDOWN {} declare interface AbstractLevelDOWNConstructor { - (location: string): AbstractLevelDOWN; + (location: string): AbstractLevelDOWN; } " `; -exports[`should remove this in call signature 1`] = ` +exports[`should keep this in call signature 1`] = ` "declare interface Arc { - (d: Datum, ...args: any[]): string | null; + (this: This, d: Datum, ...args: any[]): string | null; } declare interface D { - new(d: Datum, ...args: any[]): void; + new(this: D, d: Datum, ...args: any[]): void; } declare interface C { - (d: Datum, ...args: any[]): any; + (this: This, d: Datum, ...args: any[]): any; } " `; diff --git a/src/__tests__/function-exports.spec.ts b/src/__tests__/function-exports.spec.ts index 08d07c3e..be8c7b44 100644 --- a/src/__tests__/function-exports.spec.ts +++ b/src/__tests__/function-exports.spec.ts @@ -51,7 +51,7 @@ export function routerReducer(state?: RouterState): RouterState; expect(result).toBeValidFlowTypeDeclarations(); }); -it("should remove this annotation from functions", () => { +it("should keep this annotation in functions", () => { const ts = "function addClickListener(onclick: (this: void, e: Event) => void): void;"; const result = compiler.compileDefinitionString(ts, { quiet: true }); @@ -59,7 +59,7 @@ it("should remove this annotation from functions", () => { expect(result).toBeValidFlowTypeDeclarations(); }); -it("should remove default parameters from functions", () => { +it("should keep default parameters in functions", () => { const ts = "function addClickListener(onclick: (e: Event) => void): T;"; const result = compiler.compileDefinitionString(ts, { quiet: true }); @@ -67,6 +67,14 @@ it("should remove default parameters from functions", () => { expect(result).toBeValidFlowTypeDeclarations(); }); +it("should transform generic `` to `` on functions", () => { + const ts = + "function addClickListener(onclick: (e: Event) => void): T;"; + const result = compiler.compileDefinitionString(ts, { quiet: true }); + expect(beautify(result)).toMatchSnapshot(); + expect(result).toBeValidFlowTypeDeclarations(); +}); + it("should not break with Promise return types - issue 156", () => { const ts = "export declare const fn: () => Promise;"; const result = compiler.compileDefinitionString(ts, { quiet: true }); diff --git a/src/__tests__/interfaces.spec.ts b/src/__tests__/interfaces.spec.ts index b0aca009..370243f9 100644 --- a/src/__tests__/interfaces.spec.ts +++ b/src/__tests__/interfaces.spec.ts @@ -105,14 +105,14 @@ it("should support call signature", () => { expect(result).toBeValidFlowTypeDeclarations(); }); -it("should remove this in call signature", () => { +it("should keep this in call signature", () => { const ts = ` interface Arc { (this: This, d: Datum, ...args: any[]): string | null; } interface D { - new (this: This, d: Datum, ...args: any[]); + new (this: D, d: Datum, ...args: any[]); } interface C { @@ -124,7 +124,7 @@ interface C { expect(result).toBeValidFlowTypeDeclarations(); }); -it("should remove generic defaults in call signature", () => { +it("should keep generic defaults in call signature", () => { const ts = ` interface AbstractLevelDOWN {} interface AbstractLevelDOWNConstructor { diff --git a/src/printers/function.ts b/src/printers/function.ts index 99f49609..3c4c7adf 100644 --- a/src/printers/function.ts +++ b/src/printers/function.ts @@ -11,12 +11,8 @@ export const functionType = ( | ts.ConstructSignatureDeclaration, dotAsReturn = false, ): string => { - const params = func.parameters - .filter( - param => !(ts.isIdentifier(param.name) && param.name.text === "this"), - ) - .map(printers.common.parameter); - const generics = printers.common.genericsWithoutDefault(func.typeParameters); + const params = func.parameters.map(printers.common.parameter); + const generics = printers.common.generics(func.typeParameters); const returns = func.type ? printers.node.printType(func.type) : "void"; const firstPass = `${generics}(${params.join(", ")})${ diff --git a/src/printers/node.ts b/src/printers/node.ts index 7a016ac8..7dd34a18 100644 --- a/src/printers/node.ts +++ b/src/printers/node.ts @@ -723,12 +723,8 @@ export const printType = withEnv( case ts.SyntaxKind.CallSignature: { // TODO: rewrite to printers.functions.functionType - const generics = printers.common.genericsWithoutDefault( - type.typeParameters, - ); + const generics = printers.common.generics(type.typeParameters); const str = `${generics}(${type.parameters - // @ts-expect-error todo(flow->ts) - .filter(param => param.name.text !== "this") .map(printers.common.parameter) .join(", ")})`; // TODO: I can't understand this From ac7505db74a2e5ade4644899752be9ffd28a5d02 Mon Sep 17 00:00:00 2001 From: Dominic Tobias Date: Thu, 5 Oct 2023 00:32:48 +0100 Subject: [PATCH 6/6] feat: replace $PropertyType and $ElementType with indexed access type --- README.md | 8 +++---- .../duplicated-names.spec.ts.snap | 21 ++++++++----------- .../__snapshots__/mapped-types.spec.ts.snap | 7 ++----- src/printers/node.ts | 11 +--------- 4 files changed, 16 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 07533d0a..9fb9c349 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ It's surprisingly robust and non-lossy as it stands right now, in big part thank | | Type guards | `(a: X) => a is A` | `(a: X) => boolean` | | ✅ | Type parameter bounds | `function f(a:A){}` | `function f(a:A){}` | | ✅ | keyof X | `keyof X` | `$Keys` | -| ✅ | X[keyof X] | `X[keyof X]` | `$ElementType>` | +| ✅ | X[keyof X] | `X[keyof X]` | `X[$Keys]` | | ✅ | Partial | `Partial` | `$Rest` | | ✅ | Readonly | `Readonly` | `$ReadOnly` | | ✅ | ReadonlyArray | `ReadonlyArray` | `$ReadOnlyArray` | @@ -35,9 +35,9 @@ It's surprisingly robust and non-lossy as it stands right now, in big part thank | | InstanceType | `InstanceType` | | | ✅ | Required | `Required` | `Required` | | | ThisType | `ThisType` | | -| ✅ | T['string'] | `T['string']` | `$PropertyType` | -| ✅ | T[k] | `T[k]` | `$ElementType` | -| ✅ | Mapped types | `{[K in keyof Obj]: Obj[K]}` | `$ObjMapi(K) => $ElementType>` | +| ✅ | T['string'] | `T['string']` | `T['string']` | +| ✅ | T[k] | `T[k]` | `T[k]` | +| ✅ | Mapped types | `{[K in keyof Obj]: Obj[K]}` | `$ObjMapi(K) => Obj[K]>` | | | Conditional types | `A extends B ? C : D` | `any` | | ✅ | typeof operator | `typeof foo` | `typeof foo` | | ✅ | Tuple type | `[number, string]` | `[number, string]` | diff --git a/src/__tests__/__snapshots__/duplicated-names.spec.ts.snap b/src/__tests__/__snapshots__/duplicated-names.spec.ts.snap index 8b1c0a57..a315c844 100644 --- a/src/__tests__/__snapshots__/duplicated-names.spec.ts.snap +++ b/src/__tests__/__snapshots__/duplicated-names.spec.ts.snap @@ -13,10 +13,9 @@ declare export var AuthMechanism: { +MONGODB_CR: \\"MONGODB-CR\\", ... }; -export type AuthMechanismType1 = $ElementType< - typeof AuthMechanism, - $Keys ->; +export type AuthMechanismType1 = (typeof AuthMechanism)[$Keys< + typeof AuthMechanism +>]; " `; @@ -26,10 +25,9 @@ exports[`should handle variable & type having same name 1`] = ` +MONGODB_CR: \\"MONGODB-CR\\", ... }; -export type AuthMechanismType = $ElementType< - typeof AuthMechanism, - $Keys ->; +export type AuthMechanismType = (typeof AuthMechanism)[$Keys< + typeof AuthMechanism +>]; " `; @@ -38,10 +36,9 @@ exports[`should support generic type rename 1`] = ` +off: \\"off\\", ... }>; -export type ProfilingLevelType = $ElementType< - typeof ProfilingLevel, - $Keys ->; +export type ProfilingLevelType = (typeof ProfilingLevel)[$Keys< + typeof ProfilingLevel +>]; export type Callback = (error?: Error, result?: T) => void; declare export var callback: Callback; " diff --git a/src/__tests__/__snapshots__/mapped-types.spec.ts.snap b/src/__tests__/__snapshots__/mapped-types.spec.ts.snap index c969ac7c..99c18c79 100644 --- a/src/__tests__/__snapshots__/mapped-types.spec.ts.snap +++ b/src/__tests__/__snapshots__/mapped-types.spec.ts.snap @@ -15,10 +15,7 @@ declare type MappedUnion = $ObjMapi< { [k: SourceUnion]: any }, (K) => Ref >; -declare type MappedObj = $ObjMapi< - SourceObject, - (K) => Ref<$ElementType> ->; -declare type ConstantKey = $PropertyType; +declare type MappedObj = $ObjMapi(K) => Ref>; +declare type ConstantKey = MappedObj[\\"a\\"]; " `; diff --git a/src/printers/node.ts b/src/printers/node.ts index 7dd34a18..26fb1549 100644 --- a/src/printers/node.ts +++ b/src/printers/node.ts @@ -531,16 +531,7 @@ export const printType = withEnv( return "boolean"; case ts.SyntaxKind.IndexedAccessType: { - let fn = "$ElementType"; - if ( - ts.isLiteralTypeNode(type.indexType) && - type.indexType.literal.kind === ts.SyntaxKind.StringLiteral - ) { - fn = "$PropertyType"; - } - return `${fn}<${printType(type.objectType)}, ${printType( - type.indexType, - )}>`; + return `${printType(type.objectType)}[${printType(type.indexType)}]`; } case ts.SyntaxKind.TypeOperator: