diff --git a/changelog_unreleased/flow/19022.md b/changelog_unreleased/flow/19022.md new file mode 100644 index 000000000..16f4f4ec0 --- /dev/null +++ b/changelog_unreleased/flow/19022.md @@ -0,0 +1,19 @@ +#### Support `readonly` as a variance annotation (#19022 by @marcoww6) + +Flow now accepts `readonly` as a property variance annotation, equivalent to `+` (covariant/read-only). + + +```jsx +// Input +type T = { + readonly foo: string, +}; + +// Prettier stable +SyntaxError + +// Prettier main +type T = { + readonly foo: string, +}; +``` diff --git a/src/language-js/print/flow.js b/src/language-js/print/flow.js index 05b6c82e6..ad8e71d2d 100644 --- a/src/language-js/print/flow.js +++ b/src/language-js/print/flow.js @@ -218,8 +218,8 @@ function printFlow(path, options, print, args) { return ["?", print("typeAnnotation")]; case "Variance": { const { kind } = node; - assert.ok(kind === "plus" || kind === "minus"); - return kind === "plus" ? "+" : "-"; + assert.ok(kind === "plus" || kind === "minus" || kind === "readonly"); + return kind === "plus" ? "+" : kind === "minus" ? "-" : `${kind} `; } case "KeyofTypeAnnotation": return ["keyof ", print("argument")]; diff --git a/src/language-js/types/flow-estree.d.ts b/src/language-js/types/flow-estree.d.ts index 5b77430a4..c6ebcab2c 100644 --- a/src/language-js/types/flow-estree.d.ts +++ b/src/language-js/types/flow-estree.d.ts @@ -1200,7 +1200,7 @@ export type TypeAnnotationType = export interface Variance extends BaseNode { type: "Variance"; - kind: "plus" | "minus"; + kind: "plus" | "minus" | "readonly"; } interface BaseTypeAlias extends BaseNode { diff --git a/tests/format/flow/variance/__snapshots__/format.test.js.snap b/tests/format/flow/variance/__snapshots__/format.test.js.snap index ef9ed688a..6638d85f9 100644 --- a/tests/format/flow/variance/__snapshots__/format.test.js.snap +++ b/tests/format/flow/variance/__snapshots__/format.test.js.snap @@ -9,10 +9,40 @@ class Route { static +param: T; } +class ReadonlyRoute { + static readonly param: T; +} + +type ReadonlyObj = { + readonly foo: string, + readonly [string]: unknown +}; + +type ReadonlyTuple = [ readonly label: number ]; + +type ReadonlyInterface = interface { + readonly prop: string +}; + =====================================output===================================== class Route { static +param: T; } +class ReadonlyRoute { + static readonly param: T; +} + +type ReadonlyObj = { + readonly foo: string, + readonly [string]: unknown, +}; + +type ReadonlyTuple = [readonly label: number]; + +type ReadonlyInterface = interface { + readonly prop: string, +}; + ================================================================================ `; diff --git a/tests/format/flow/variance/variance.js b/tests/format/flow/variance/variance.js index 72404fa71..1858cd7d2 100644 --- a/tests/format/flow/variance/variance.js +++ b/tests/format/flow/variance/variance.js @@ -1,3 +1,18 @@ class Route { static +param: T; } + +class ReadonlyRoute { + static readonly param: T; +} + +type ReadonlyObj = { + readonly foo: string, + readonly [string]: unknown +}; + +type ReadonlyTuple = [ readonly label: number ]; + +type ReadonlyInterface = interface { + readonly prop: string +};