Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[babel 8] Type checking preset-typescript options (#12460)
* refactor: extract option normalization in preset-typescript * breaking: type checking preset-typescript options * chore: bundle preset-typescript into a single lib * test: disable Babel 7 test on Babel 8 breaking change test * workaround Jest 24 error snapshot dedent issue * skip Babel 8 test when the Breaking ENV is not available * chore: update test snapshot * Update packages/babel-preset-typescript/test/normalize-options.spec.js Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com> * update test fixtures Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
- Loading branch information
1 parent
866a742
commit ff52ace
Showing
4 changed files
with
171 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { OptionValidator } from "@babel/helper-validator-option"; | ||
const v = new OptionValidator("@babel/preset-typescript"); | ||
|
||
export default function normalizeOptions(options = {}) { | ||
let { | ||
allowDeclareFields, | ||
allowNamespaces, | ||
jsxPragma, | ||
onlyRemoveTypeImports, | ||
} = options; | ||
|
||
if (process.env.BABEL_8_BREAKING) { | ||
const TopLevelOptions = { | ||
allowDeclareFields: "allowDeclareFields", | ||
allExtensions: "allExtensions", | ||
allowNamespaces: "allowNamespaces", | ||
isTSX: "isTSX", | ||
jsxPragma: "jsxPragma", | ||
jsxPragmaFrag: "jsxPragmaFrag", | ||
onlyRemoveTypeImports: "onlyRemoveTypeImports", | ||
}; | ||
v.validateTopLevelOptions(options, TopLevelOptions); | ||
allowDeclareFields = v.validateBooleanOption( | ||
TopLevelOptions.allowDeclareFields, | ||
options.allowDeclareFields, | ||
true, | ||
); | ||
allowNamespaces = v.validateBooleanOption( | ||
TopLevelOptions.allowNamespaces, | ||
options.allowNamespaces, | ||
true, | ||
); | ||
jsxPragma = v.validateStringOption( | ||
TopLevelOptions.jsxPragma, | ||
options.jsxPragma, | ||
"React", | ||
); | ||
onlyRemoveTypeImports = v.validateBooleanOption( | ||
TopLevelOptions.onlyRemoveTypeImports, | ||
options.onlyRemoveTypeImports, | ||
true, | ||
); | ||
} | ||
|
||
const jsxPragmaFrag = v.validateStringOption( | ||
"jsxPragmaFrag", | ||
options.jsxPragmaFrag, | ||
"React.Fragment", | ||
); | ||
|
||
const allExtensions = v.validateBooleanOption( | ||
"allExtensions", | ||
options.allExtensions, | ||
false, | ||
); | ||
|
||
const isTSX = v.validateBooleanOption("isTSX", options.isTSX, false); | ||
|
||
if (isTSX) { | ||
v.invariant(allExtensions, "isTSX:true requires allExtensions:true"); | ||
} | ||
|
||
return { | ||
allExtensions, | ||
allowDeclareFields, | ||
allowNamespaces, | ||
isTSX, | ||
jsxPragma, | ||
jsxPragmaFrag, | ||
onlyRemoveTypeImports, | ||
}; | ||
} |
93 changes: 93 additions & 0 deletions
93
packages/babel-preset-typescript/test/normalize-options.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import normalizeOptions from "../src/normalize-options"; | ||
describe("normalize options", () => { | ||
(process.env.BABEL_8_BREAKING ? describe : describe.skip)("Babel 8", () => { | ||
it("should throw on unknown options", () => { | ||
expect(() => normalizeOptions({ allowNamespace: true })).toThrowError( | ||
"@babel/preset-typescript: 'allowNamespace' is not a valid top-level option.\n- Did you mean 'allowNamespaces'?", | ||
); | ||
}); | ||
it.each([ | ||
"allowDeclareFields", | ||
"allExtensions", | ||
"allowNamespaces", | ||
"isTSX", | ||
"onlyRemoveTypeImports", | ||
])("should throw when `%p` is not a boolean", optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( | ||
`@babel/preset-typescript: '${optionName}' option must be a boolean.`, | ||
); | ||
}); | ||
it.each(["jsxPragma", "jsxPragmaFrag"])( | ||
"should throw when `%p` is not a string", | ||
optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( | ||
`@babel/preset-typescript: '${optionName}' option must be a string.`, | ||
); | ||
}, | ||
); | ||
it("should not throw when options is not defined", () => { | ||
expect(() => normalizeOptions()).not.toThrowError(); | ||
}); | ||
it("default values", () => { | ||
expect(normalizeOptions({})).toMatchInlineSnapshot(` | ||
Object { | ||
"allExtensions": false, | ||
"allowDeclareFields": true, | ||
"allowNamespaces": true, | ||
"isTSX": false, | ||
"jsxPragma": "React", | ||
"jsxPragmaFrag": "React.Fragment", | ||
"onlyRemoveTypeImports": true, | ||
} | ||
`); | ||
}); | ||
}); | ||
(process.env.BABEL_8_BREAKING ? describe.skip : describe)("Babel 7", () => { | ||
it("should not throw on unknown options", () => { | ||
expect(() => | ||
normalizeOptions({ allowNamespace: true }), | ||
).not.toThrowError(); | ||
}); | ||
it.each(["allowDeclareFields", "allowNamespaces", "onlyRemoveTypeImports"])( | ||
"should not throw when `%p` is not a boolean", | ||
optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).not.toThrowError(); | ||
}, | ||
); | ||
it.each(["jsxPragma"])( | ||
"should throw when `%p` is not a string", | ||
optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).not.toThrowError(); | ||
}, | ||
); | ||
it.each(["allExtensions", "isTSX"])( | ||
"should throw when `%p` is not a boolean", | ||
optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( | ||
`@babel/preset-typescript: '${optionName}' option must be a boolean.`, | ||
); | ||
}, | ||
); | ||
it.each(["jsxPragmaFrag"])( | ||
"should throw when `%p` is not a string", | ||
optionName => { | ||
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( | ||
`@babel/preset-typescript: '${optionName}' option must be a string.`, | ||
); | ||
}, | ||
); | ||
it("default values", () => { | ||
expect(normalizeOptions({})).toMatchInlineSnapshot(` | ||
Object { | ||
"allExtensions": false, | ||
"allowDeclareFields": undefined, | ||
"allowNamespaces": undefined, | ||
"isTSX": false, | ||
"jsxPragma": undefined, | ||
"jsxPragmaFrag": "React.Fragment", | ||
"onlyRemoveTypeImports": undefined, | ||
} | ||
`); | ||
}); | ||
}); | ||
}); |