Support (type) satisfies never; (#15514)
This commit is contained in:
1 parent
d0b907620b
commit
c609058fd3
10 files changed
+409
-7
No files matched your search
@@ -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;
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user