Support (type) satisfies never; (#15514)

This commit is contained in:
Seiya authored and GitHub committed 2023-10-16 16:04:28 +09:00
1 parent d0b907620b
commit c609058fd3
10 files changed
+409 -7

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
#### Keep required parenthesis around some specific keyword like identifiers in expression statement of satisfies / as expression (#15514 by @seiyab)
<!-- prettier-ignore -->
```ts
// Input
(type) satisfies never;
// Prettier stable
type satisfies never;
// Prettier main
(type) satisfies never;
```
+23
View File
@@ -110,6 +110,29 @@ function needsParens(path, options) {
}
}
// `(type) satisfies never;` and similar cases
if (key === "expression") {
switch (node.name) {
case "await":
case "interface":
case "module":
case "using":
case "yield":
case "let":
case "type": {
const ancestorNeitherAsNorSatisfies = path.findAncestor(
(node) => !isBinaryCastExpression(node),
);
if (
ancestorNeitherAsNorSatisfies !== parent &&
ancestorNeitherAsNorSatisfies.type === "ExpressionStatement"
) {
return true;
}
}
}
}
return false;
}
@@ -56,6 +56,8 @@ const iter2 = createIterator(self.controller, child, self.tag as BlahFunctionCom
x as any as T;
(type) as T;
=====================================output=====================================
// @flow
@@ -123,6 +125,8 @@ const iter2 = createIterator(
x as any as T;
(type) as T;
================================================================================
`;
@@ -132,7 +136,9 @@ exports[`as-const.js [babel-flow] format 1`] = `
11 | DEBUG: 7,
> 12 | } as const;
| ^
13 |"
13 |
14 | (type) as const;
15 |"
`;
exports[`as-const.js format 1`] = `
@@ -154,6 +160,8 @@ export const LOG_LEVEL = {
DEBUG: 7,
} as const;
(type) as const;
=====================================output=====================================
// @flow
@@ -168,6 +176,8 @@ export const LOG_LEVEL = {
DEBUG: 7,
} as const;
(type) as const;
================================================================================
`;
@@ -400,12 +410,14 @@ function foo() {
`;
exports[`satisfies.js [babel-flow] format 1`] = `
"Missing semicolon. (3:12)
1 | // @flow
2 |
> 3 | const x = y satisfies T;
| ^
4 |"
"Unexpected token, expected "type" (32:8)
30 | satisfies satisfies mixed;
31 | as satisfies mixed;
> 32 | opaque satisfies mixed;
| ^
33 |
34 | abc satisfies mixed; // not a keyword
35 | }"
`;
exports[`satisfies.js format 1`] = `
@@ -418,11 +430,85 @@ printWidth: 80
const x = y satisfies T;
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = (type: 'foo' | 'bar') => {
switch (type) {
case 'foo':
return 1;
case 'bar':
return 2;
default:
// exhaustiveness check idiom
(type) satisfies empty;
throw new Error('unreachable');
}
}
function needParens() {
(let) satisfies mixed;
(interface) satisfies mixed;
(module) satisfies mixed;
(using) satisfies mixed;
(yield) satisfies mixed;
(await) satisfies mixed;
}
function noNeedParens() {
async satisfies mixed;
satisfies satisfies mixed;
as satisfies mixed;
opaque satisfies mixed;
abc satisfies mixed; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies empty satisfies mixed;
}
=====================================output=====================================
// @flow
const x = y satisfies T;
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = (type: "foo" | "bar") => {
switch (type) {
case "foo":
return 1;
case "bar":
return 2;
default:
// exhaustiveness check idiom
(type) satisfies empty;
throw new Error("unreachable");
}
};
function needParens() {
(let) satisfies mixed;
(interface) satisfies mixed;
(module) satisfies mixed;
(using) satisfies mixed;
(yield) satisfies mixed;
(await) satisfies mixed;
}
function noNeedParens() {
async satisfies mixed;
satisfies satisfies mixed;
as satisfies mixed;
opaque satisfies mixed;
abc satisfies mixed; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies empty satisfies mixed;
}
================================================================================
`;
@@ -10,3 +10,5 @@ export const LOG_LEVEL = {
INFO: 6,
DEBUG: 7,
} as const;
(type) as const;
@@ -36,3 +36,5 @@ const iter1 = createIterator(this.controller, child, this.tag as BlahFunctionCom
const iter2 = createIterator(self.controller, child, self.tag as BlahFunctionComponent);
x as any as T;
(type) as T;
@@ -1,3 +1,40 @@
// @flow
const x = y satisfies T;
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = (type: 'foo' | 'bar') => {
switch (type) {
case 'foo':
return 1;
case 'bar':
return 2;
default:
// exhaustiveness check idiom
(type) satisfies empty;
throw new Error('unreachable');
}
}
function needParens() {
(let) satisfies mixed;
(interface) satisfies mixed;
(module) satisfies mixed;
(using) satisfies mixed;
(yield) satisfies mixed;
(await) satisfies mixed;
}
function noNeedParens() {
async satisfies mixed;
satisfies satisfies mixed;
as satisfies mixed;
opaque satisfies mixed;
abc satisfies mixed; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies empty satisfies mixed;
}
@@ -327,6 +327,26 @@ export default (function log() {} as typeof console.log);
================================================================================
`;
exports[`expression-statement.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
// expression statemnt of "as" expression hardly ever makes sense, but it's still valid.
const [type, x] = [0, 0];
(type) as unknown;
x as unknown;
=====================================output=====================================
// expression statemnt of "as" expression hardly ever makes sense, but it's still valid.
const [type, x] = [0, 0];
(type) as unknown;
x as unknown;
================================================================================
`;
exports[`long-identifiers.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
@@ -0,0 +1,4 @@
// expression statemnt of "as" expression hardly ever makes sense, but it's still valid.
const [type, x] = [0, 0];
(type) as unknown;
x as unknown;
@@ -498,6 +498,181 @@ export default (function log() {} satisfies typeof console.log);
================================================================================
`;
exports[`expression-statement.ts - {"semi":false} format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
let type: 'foo' | 'bar' = 'foo';
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = () => {
switch (type) {
case 'foo':
return 1;
case 'bar':
return 2;
default:
// exhaustiveness check idiom
(type) satisfies never;
throw new Error('unreachable');
}
}
function needParens() {
(let) satisfies unknown;
(interface) satisfies unknown;
(module) satisfies unknown;
(using) satisfies unknown;
(yield) satisfies unknown;
(await) satisfies unknown;
}
function noNeedParens() {
async satisfies unknown;
satisfies satisfies unknown;
as satisfies unknown;
abc satisfies unknown; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies never satisfies unknown;
}
=====================================output=====================================
let type: "foo" | "bar" = "foo"
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = () => {
switch (type) {
case "foo":
return 1
case "bar":
return 2
default:
// exhaustiveness check idiom
;(type) satisfies never
throw new Error("unreachable")
}
}
function needParens() {
;(let) satisfies unknown
;(interface) satisfies unknown
;(module) satisfies unknown
;(using) satisfies unknown
;(yield) satisfies unknown
;(await) satisfies unknown
}
function noNeedParens() {
async satisfies unknown
satisfies satisfies unknown
as satisfies unknown
abc satisfies unknown // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies
;(type) satisfies never satisfies unknown
}
================================================================================
`;
exports[`expression-statement.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
let type: 'foo' | 'bar' = 'foo';
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = () => {
switch (type) {
case 'foo':
return 1;
case 'bar':
return 2;
default:
// exhaustiveness check idiom
(type) satisfies never;
throw new Error('unreachable');
}
}
function needParens() {
(let) satisfies unknown;
(interface) satisfies unknown;
(module) satisfies unknown;
(using) satisfies unknown;
(yield) satisfies unknown;
(await) satisfies unknown;
}
function noNeedParens() {
async satisfies unknown;
satisfies satisfies unknown;
as satisfies unknown;
abc satisfies unknown; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies never satisfies unknown;
}
=====================================output=====================================
let type: "foo" | "bar" = "foo";
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = () => {
switch (type) {
case "foo":
return 1;
case "bar":
return 2;
default:
// exhaustiveness check idiom
(type) satisfies never;
throw new Error("unreachable");
}
};
function needParens() {
(let) satisfies unknown;
(interface) satisfies unknown;
(module) satisfies unknown;
(using) satisfies unknown;
(yield) satisfies unknown;
(await) satisfies unknown;
}
function noNeedParens() {
async satisfies unknown;
satisfies satisfies unknown;
as satisfies unknown;
abc satisfies unknown; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies never satisfies unknown;
}
================================================================================
`;
exports[`gt-lt.ts - {"semi":false} format 1`] = `
====================================options=====================================
parsers: ["typescript"]
@@ -0,0 +1,38 @@
let type: 'foo' | 'bar' = 'foo';
// demonstrating how "satisfies" expression can be practically used as expression statement.
const _ = () => {
switch (type) {
case 'foo':
return 1;
case 'bar':
return 2;
default:
// exhaustiveness check idiom
(type) satisfies never;
throw new Error('unreachable');
}
}
function needParens() {
(let) satisfies unknown;
(interface) satisfies unknown;
(module) satisfies unknown;
(using) satisfies unknown;
(yield) satisfies unknown;
(await) satisfies unknown;
}
function noNeedParens() {
async satisfies unknown;
satisfies satisfies unknown;
as satisfies unknown;
abc satisfies unknown; // not a keyword
}
function satisfiesChain() {
satisfies satisfies satisfies satisfies satisfies;
(type) satisfies never satisfies unknown;
}