chore: upgrade to TypeScript 3.5 (#5556)

TS 3.5 got much stricter on writing changes to objects with varied types [1] so we have to do a bit of typecasting work to convince TS about the types of keys and values that we are setting.

Longer term we should think about a better data structure that avoids us having to jump through some hoops but for now I think this is a reasonable step to get us onto 3.5.

Same story regarding bindings on `window`: the easiest fix is to cast `window` to `any` for the code that adds to it. I'm sure we can come up with a more type-safe way of doing this in the future.

[1]: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#fixes-to-unsound-writes-to-indexed-access-types
This commit is contained in:
Jack Franklin 2020-03-31 09:48:09 +01:00 committed by GitHub
parent b9240b1664
commit 5e8d79bf98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 18 deletions

View File

@ -329,7 +329,9 @@ class AXNode {
role: this._role
};
/** @type {!Array<keyof SerializedAXNode>} */
/** @enum {'name'|'value'|'description'|'keyshortcuts'|'roledescription'|'valuetext'} */
let UserStringProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<UserStringProperties>} */
const userStringProperties = [
'name',
'value',
@ -338,13 +340,21 @@ class AXNode {
'roledescription',
'valuetext',
];
/**
* @param {UserStringProperties} key
*/
const getUserStringPropertyValue = key => /** @type string */(properties.get(key));
for (const userStringProperty of userStringProperties) {
if (!properties.has(userStringProperty))
continue;
node[userStringProperty] = properties.get(userStringProperty);
node[userStringProperty] = getUserStringPropertyValue(userStringProperty);
}
/** @type {!Array<keyof SerializedAXNode>} */
/** @enum {'disabled'|'expanded'|'focused'|'modal'|'multiline'|'multiselectable'|'readonly'|'required'|'selected'} */
let BooleanProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<BooleanProperties>} */
const booleanProperties = [
'disabled',
'expanded',
@ -356,18 +366,25 @@ class AXNode {
'required',
'selected',
];
/**
* @param {BooleanProperties} key
*/
const getBooleanPropertyValue = key => /** @type boolean */(properties.get(key));
for (const booleanProperty of booleanProperties) {
// WebArea's treat focus differently than other nodes. They report whether their frame has focus,
// not whether focus is specifically on the root node.
if (booleanProperty === 'focused' && this._role === 'WebArea')
continue;
const value = properties.get(booleanProperty);
const value = getBooleanPropertyValue(booleanProperty);
if (!value)
continue;
node[booleanProperty] = value;
node[booleanProperty] = getBooleanPropertyValue(booleanProperty);
}
/** @type {!Array<keyof SerializedAXNode>} */
/** @enum {'checked'|'pressed'} */
let TristateProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<TristateProperties>} */
const tristateProperties = [
'checked',
'pressed',
@ -378,29 +395,45 @@ class AXNode {
const value = properties.get(tristateProperty);
node[tristateProperty] = value === 'mixed' ? 'mixed' : value === 'true' ? true : false;
}
/** @type {!Array<keyof SerializedAXNode>} */
/** @enum {'level'|'valuemax'|'valuemin'} */
let NumericalProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<NumericalProperties>} */
const numericalProperties = [
'level',
'valuemax',
'valuemin',
];
/**
* @param {NumericalProperties} key
*/
const getNumericalPropertyValue = key => /** @type number */(properties.get(key));
for (const numericalProperty of numericalProperties) {
if (!properties.has(numericalProperty))
continue;
node[numericalProperty] = properties.get(numericalProperty);
node[numericalProperty] = getNumericalPropertyValue(numericalProperty);
}
/** @type {!Array<keyof SerializedAXNode>} */
/** @enum {'autocomplete'|'haspopup'|'invalid'|'orientation'} */
let TokenProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<TokenProperties>} */
const tokenProperties = [
'autocomplete',
'haspopup',
'invalid',
'orientation',
];
/**
* @param {TokenProperties} key
*/
const getTokenPropertyValue = key => /** @type string */(properties.get(key));
for (const tokenProperty of tokenProperties) {
const value = properties.get(tokenProperty);
const value = getTokenPropertyValue(tokenProperty);
if (!value || value === 'false')
continue;
node[tokenProperty] = value;
node[tokenProperty] = getTokenPropertyValue(tokenProperty);
}
return node;
}

View File

@ -444,8 +444,10 @@ class Page extends EventEmitter {
await Promise.all(this.frames().map(frame => frame.evaluate(expression).catch(debugError)));
function addPageBinding(bindingName) {
const binding = window[bindingName];
window[bindingName] = (...args) => {
const win = /** @type * */ (window);
const binding = /** @type function(string):* */ (win[bindingName]);
win[bindingName] = (...args) => {
const me = window[bindingName];
let callbacks = me['callbacks'];
if (!callbacks) {
@ -677,10 +679,12 @@ class Page extends EventEmitter {
* @return {!Promise<?Puppeteer.Response>}
*/
async reload(options) {
const [response] = await Promise.all([
const result = await Promise.all([
this.waitForNavigation(options),
this._client.send('Page.reload')
]);
const response = /** @type Puppeteer.Response */ (result[0]);
return response;
}
@ -759,10 +763,11 @@ class Page extends EventEmitter {
const entry = history.entries[history.currentIndex + delta];
if (!entry)
return null;
const [response] = await Promise.all([
const result = await Promise.all([
this.waitForNavigation(options),
this._client.send('Page.navigateToHistoryEntry', {entryId: entry.id}),
]);
const response = /** @type Puppeteer.Response */ (result[0]);
return response;
}

View File

@ -21,7 +21,7 @@
"lint": "([ \"$CI\" = true ] && eslint --quiet -f codeframe . || eslint .) && npm run tsc && npm run doc",
"doc": "node utils/doclint/cli.js",
"coverage": "cross-env COVERAGE=true npm run unit",
"tsc": "tsc -p .",
"tsc": "tsc --version && tsc -p .",
"apply-next-version": "node utils/apply_next_version.js",
"bundle": "npx browserify -r ./index.js:puppeteer -o utils/browser/puppeteer-web.js",
"test-types": "node utils/doclint/generate_types && npx -p typescript@3.2 tsc -p utils/doclint/generate_types/test/",
@ -61,7 +61,7 @@
"pixelmatch": "^4.0.2",
"pngjs": "^3.3.3",
"text-diff": "^1.0.1",
"typescript": "3.2.2"
"typescript": "3.5.3"
},
"browser": {
"./lib/BrowserFetcher.js": false,

View File

@ -98,7 +98,7 @@ function checkSources(sources) {
function serializeSymbol(symbol, circular = []) {
const type = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
const name = symbol.getName();
if (symbol.valueDeclaration.dotDotDotToken) {
if (symbol.valueDeclaration && symbol.valueDeclaration.dotDotDotToken) {
const innerType = serializeType(type.typeArguments[0], circular);
innerType.name = '...' + innerType.name;
return Documentation.Member.createProperty('...' + name, innerType);
@ -120,6 +120,12 @@ function checkSources(sources) {
return false;
if (type.getCallSignatures().length)
return false;
if (type.isLiteral())
return false;
if (type.isUnion())
return false;
return true;
}