diff --git a/package-lock.json b/package-lock.json index ad3ba37c3..edb9988ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.21.0", "@hot-loader/react-dom": "^16.13.0", + "@reduxjs/toolkit": "^1.9.7", "argparse": "^1.0.10", "babel-loader": "^8.0.4", "babel-plugin-lodash": "^3.3.4", @@ -78,8 +79,6 @@ "react-tooltip": "^4.2.10", "react-transition-group": "^1.2.1", "react-virtualized": "^9.22.3", - "redux": "^4.0.1", - "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.5", "style-loader": "^0.13.2", "styled-components": "^4.0.3", @@ -98,6 +97,7 @@ "devDependencies": { "@types/leaflet": "^1.9.3", "@types/node": "^18.15.11", + "@types/webpack-env": "^1.18.2", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "chai": "^4.1.2", @@ -2953,6 +2953,29 @@ "node": ">=12" } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -3271,6 +3294,12 @@ "source-map": "^0.6.0" } }, + "node_modules/@types/webpack-env": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.2.tgz", + "integrity": "sha512-BFqcTHHTrrI8EBmIzNAmLPP3IqtEG9J1IPFWbPeS/F0/TGNmo0pI5svOa7JbMF9vSCXQCvJWT2gxLJNVuf9blw==", + "dev": true + }, "node_modules/@types/webpack-sources": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", @@ -8130,6 +8159,15 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -12460,17 +12498,17 @@ } }, "node_modules/redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "dependencies": { "@babel/runtime": "^7.9.2" } }, "node_modules/redux-thunk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.0.tgz", - "integrity": "sha512-/y6ZKQNU/0u8Bm7ROLq9Pt/7lU93cT0IucYMrubo89ENjxPa7i8pqLKu6V4X7/TvYovQ6x01unTeyeZ9lgXiTA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "peerDependencies": { "redux": "^4" } @@ -12594,6 +12632,11 @@ "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=" }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", @@ -16616,6 +16659,17 @@ } } }, + "@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "requires": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + } + }, "@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -16940,6 +16994,12 @@ } } }, + "@types/webpack-env": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.2.tgz", + "integrity": "sha512-BFqcTHHTrrI8EBmIzNAmLPP3IqtEG9J1IPFWbPeS/F0/TGNmo0pI5svOa7JbMF9vSCXQCvJWT2gxLJNVuf9blw==", + "dev": true + }, "@types/webpack-sources": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", @@ -20571,6 +20631,11 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, + "immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -23760,17 +23825,17 @@ } }, "redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "requires": { "@babel/runtime": "^7.9.2" } }, "redux-thunk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.0.tgz", - "integrity": "sha512-/y6ZKQNU/0u8Bm7ROLq9Pt/7lU93cT0IucYMrubo89ENjxPa7i8pqLKu6V4X7/TvYovQ6x01unTeyeZ9lgXiTA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "requires": {} }, "regenerate": { @@ -23870,6 +23935,11 @@ "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=" }, + "reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", diff --git a/package.json b/package.json index efcf9decb..ebaa77595 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.21.0", "@hot-loader/react-dom": "^16.13.0", + "@reduxjs/toolkit": "^1.9.7", "argparse": "^1.0.10", "babel-loader": "^8.0.4", "babel-plugin-lodash": "^3.3.4", @@ -108,8 +109,6 @@ "react-tooltip": "^4.2.10", "react-transition-group": "^1.2.1", "react-virtualized": "^9.22.3", - "redux": "^4.0.1", - "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.5", "style-loader": "^0.13.2", "styled-components": "^4.0.3", @@ -125,6 +124,7 @@ "devDependencies": { "@types/leaflet": "^1.9.3", "@types/node": "^18.15.11", + "@types/webpack-env": "^1.18.2", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "chai": "^4.1.2", diff --git a/src/components/controls/measurementsOptions.js b/src/components/controls/measurementsOptions.js index dee0fa21d..28f760013 100644 --- a/src/components/controls/measurementsOptions.js +++ b/src/components/controls/measurementsOptions.js @@ -1,5 +1,6 @@ import React from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useSelector } from "react-redux"; +import { useAppDispatch } from "../../hooks"; import { isEqual } from "lodash"; import { changeMeasurementsCollection } from "../../actions/measurements"; import { @@ -30,7 +31,7 @@ const collectionOptionsSelector = (collections) => { }; const MeasurementsOptions = () => { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const collection = useSelector((state) => state.measurements.collectionToDisplay); const collectionOptions = useSelector((state) => collectionOptionsSelector(state.measurements.collections), isEqual); const groupBy = useSelector((state) => state.controls.measurementsGroupBy); diff --git a/src/components/controls/panel-toggles.js b/src/components/controls/panel-toggles.js deleted file mode 100644 index 145eadd30..000000000 --- a/src/components/controls/panel-toggles.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { withTranslation } from 'react-i18next'; - -import Toggle from "./toggle"; -import { togglePanelDisplay } from "../../actions/panelDisplay"; - -@connect((state) => ({ - panelsAvailable: state.controls.panelsAvailable, - panelsToDisplay: state.controls.panelsToDisplay, - showTreeToo: state.controls.showTreeToo -})) -class PanelToggles extends React.Component { - render() { - const { t } = this.props; - - const panels = this.props.panelsAvailable.slice(); - if (this.props.showTreeToo && panels.indexOf("map") !== -1) { - panels.splice(panels.indexOf("map"), 1); - } - return panels.map((n) => ( - this.props.dispatch(togglePanelDisplay(n))} - label={t("sidebar:Show " + n)} - style={{paddingBottom: "10px"}} - /> - )); - } -} - -const WithTranslation = withTranslation()(PanelToggles); -export default WithTranslation; diff --git a/src/components/controls/panel-toggles.tsx b/src/components/controls/panel-toggles.tsx new file mode 100644 index 000000000..023ea9bae --- /dev/null +++ b/src/components/controls/panel-toggles.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { useSelector } from "react-redux"; +import { useAppDispatch } from "../../hooks"; +import { useTranslation } from 'react-i18next'; + +import Toggle from "./toggle"; +import { togglePanelDisplay } from "../../actions/panelDisplay"; +import { RootState } from "../../store"; + +export default function PanelToggles() { + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + + const panelsAvailable = useSelector((state: RootState) => state.controls.panelsAvailable); + const panelsToDisplay = useSelector((state: RootState) => state.controls.panelsToDisplay); + const showTreeToo = useSelector((state: RootState) => state.controls.showTreeToo); + + const panels = panelsAvailable.slice(); + if (showTreeToo && panels.indexOf("map") !== -1) { + panels.splice(panels.indexOf("map"), 1); + } + return <> + {panels.map((n) => ( + dispatch(togglePanelDisplay(n))} + label={t("sidebar:Show " + n)} + style={{ paddingBottom: "10px" }} + /> + ))} + +} diff --git a/src/components/narrativeEditor/examineNarrative.js b/src/components/narrativeEditor/examineNarrative.js index 25eed58c4..8ee0b7bc8 100644 --- a/src/components/narrativeEditor/examineNarrative.js +++ b/src/components/narrativeEditor/examineNarrative.js @@ -1,5 +1,5 @@ import React, { useRef, useEffect } from "react"; -import { useDispatch } from 'react-redux'; +import { useAppDispatch } from "../../hooks"; import { getDatasetNamesFromUrl } from "../../actions/loadData"; import { CLEAN_START } from "../../actions/types"; import { createStateFromQueryOrJSONs } from "../../actions/recomputeReduxState"; @@ -159,7 +159,7 @@ const NarrativeSummary = ({summary, datasetResponses, showNarrative}) => { }; const ExamineNarrative = ({narrative, datasetResponses, setDisplayNarrative}) => { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const el = useRef(null); useEffect(() => { /* when a narrative is loaded then we want to focus on however diff --git a/src/components/narrativeEditor/useDatasetFetch.js b/src/components/narrativeEditor/useDatasetFetch.js index 3c146f4fe..9ce53c3e2 100644 --- a/src/components/narrativeEditor/useDatasetFetch.js +++ b/src/components/narrativeEditor/useDatasetFetch.js @@ -1,5 +1,5 @@ import {useEffect, useReducer, useRef} from "react"; -import { useDispatch } from 'react-redux'; +import { useAppDispatch } from "../../hooks"; import { CACHE_JSONS } from "../../actions/types"; import { FetchError } from "../../util/exceptions"; @@ -14,7 +14,7 @@ import { FetchError } from "../../util/exceptions"; */ export function useDatasetFetch(datasets) { - const dispatchRedux = useDispatch(); + const dispatchRedux = useAppDispatch; const [datasetResponses, dispatchDatasetResponses] = useReducer( (state, action) => { if (action.reset) return {}; diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 000000000..6a8507c8a --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,6 @@ +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import type { RootState, AppDispatch } from './store' + + +export const useAppDispatch: () => AppDispatch = useDispatch +export const useAppSelector: TypedUseSelectorHook = useSelector diff --git a/src/index.js b/src/index.js index 050bd95a4..d831a0c6c 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; /* A U S P I C E I M P O R T S */ -import configureStore from "./store"; +import store from "./store"; import { initialiseGoogleAnalyticsIfRequired } from "./util/googleAnalytics"; import Root from "./root"; /* I N T E R N A T I O N A L I Z A T I O N */ @@ -26,8 +26,6 @@ import "./css/select.css"; /* FONTS */ import 'typeface-lato'; -const store = configureStore(); - /* set up non-redux state storage for the animation - use this conservitavely! */ if (!window.NEXTSTRAIN) {window.NEXTSTRAIN = {};} diff --git a/src/reducers/controls.js b/src/reducers/controls.ts similarity index 95% rename from src/reducers/controls.js rename to src/reducers/controls.ts index 0691f3cba..58b20293f 100644 --- a/src/reducers/controls.js +++ b/src/reducers/controls.ts @@ -12,11 +12,22 @@ import { calcBrowserDimensionsInitialState } from "./browserDimensions"; import { doesColorByHaveConfidence } from "../actions/recomputeReduxState"; import { hasMultipleGridPanels } from "../actions/panelDisplay"; +export interface ControlsState { + panelsAvailable: string[] + panelsToDisplay: string[] + showTreeToo: boolean + canTogglePanelLayout: boolean + + // This allows arbitrary prop names while TypeScript adoption is incomplete. + // TODO: add all other props explicitly and remove this. + [propName: string]: any; +} + /* defaultState is a fn so that we can re-create it at any time, e.g. if we want to revert things (e.g. on dataset change) */ export const getDefaultControlsState = () => { - const defaults = { + const defaults: Partial = { distanceMeasure: defaultDistanceMeasure, layout: defaultLayout, geoResolution: defaultGeoResolution, @@ -80,7 +91,7 @@ export const getDefaultControlsState = () => { panelsToDisplay: [], panelLayout: calcBrowserDimensionsInitialState().width > twoColumnBreakpoint ? "grid" : "full", tipLabelKey: defaults.tipLabelKey, - showTreeToo: undefined, + showTreeToo: false, showTangle: false, zoomMin: undefined, zoomMax: undefined, @@ -102,7 +113,7 @@ export const getDefaultControlsState = () => { /* while this may change, div currently doesn't have CIs, so they shouldn't be displayed. */ export const shouldDisplayTemporalConfidence = (exists, distMeasure, layout) => exists && distMeasure === "num_date" && layout === "rect"; -const Controls = (state = getDefaultControlsState(), action) => { +const Controls = (state: ControlsState = getDefaultControlsState(), action): ControlsState => { switch (action.type) { case types.URL_QUERY_CHANGE_WITH_COMPUTED_STATE: /* fallthrough */ case types.CLEAN_START: @@ -142,7 +153,7 @@ const Controls = (state = getDefaultControlsState(), action) => { }) }); case types.CHANGE_DISTANCE_MEASURE: { - const updatesToState = { + const updatesToState: Partial = { distanceMeasure: action.data, branchLengthsToDisplay: state.branchLengthsToDisplay }; @@ -161,7 +172,7 @@ const Controls = (state = getDefaultControlsState(), action) => { return Object.assign({}, state, updatesToState); } case types.CHANGE_DATES_VISIBILITY_THICKNESS: { - const newDates = { quickdraw: action.quickdraw }; + const newDates: Partial = { quickdraw: action.quickdraw }; if (action.dateMin) { newDates.dateMin = action.dateMin; newDates.dateMinNumeric = action.dateMinNumeric; @@ -257,7 +268,7 @@ const Controls = (state = getDefaultControlsState(), action) => { }); case types.REMOVE_TREE_TOO: return Object.assign({}, state, { - showTreeToo: undefined, + showTreeToo: false, showTangle: false, canTogglePanelLayout: hasMultipleGridPanels(state.panelsAvailable), panelsToDisplay: state.panelsAvailable.slice() diff --git a/src/store.ts b/src/store.ts new file mode 100644 index 000000000..8ea3bee76 --- /dev/null +++ b/src/store.ts @@ -0,0 +1,38 @@ +import { configureStore } from '@reduxjs/toolkit'; +import { changeURLMiddleware } from "./middleware/changeURL"; +import rootReducer from "./reducers"; +// import { loggingMiddleware } from "./middleware/logActions"; +import { keepScatterplotStateInSync } from "./middleware/scatterplot"; + +const middleware = [ + keepScatterplotStateInSync, + changeURLMiddleware, + // loggingMiddleware +]; + +const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + // TODO: Go through reducers and see why the state is not immutable nor serializable. + // These were not checked prior to the adoption of Redux Toolkit, and were not + // investigated to minimize conversion efforts. + immutableCheck: false, + serializableCheck: false + }).concat(middleware), + devTools: process.env.NODE_ENV !== 'production', +}) + +if (process.env.NODE_ENV !== 'production' && module.hot) { + // console.log("hot reducer reload"); + module.hot.accept('./reducers', () => { + const nextRootReducer = require('./reducers/index'); + store.replaceReducer(nextRootReducer); + }); +} + +// Infer types from the store. +export type RootState = ReturnType +export type AppDispatch = typeof store.dispatch + +export default store; diff --git a/src/store/index.js b/src/store/index.js deleted file mode 100644 index 31b5fba63..000000000 --- a/src/store/index.js +++ /dev/null @@ -1,30 +0,0 @@ -import { createStore, applyMiddleware, compose } from "redux"; -import thunk from "redux-thunk"; -import { changeURLMiddleware } from "../middleware/changeURL"; -import rootReducer from "../reducers"; -import { loggingMiddleware } from "../middleware/logActions"; // eslint-disable-line @typescript-eslint/no-unused-vars -import { keepScatterplotStateInSync } from "../middleware/scatterplot"; - -const configureStore = (initialState) => { - const middleware = [ - thunk, - keepScatterplotStateInSync, - changeURLMiddleware, - // loggingMiddleware - ]; - const composedEnhancers = compose( - applyMiddleware(...middleware), - window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (f) => f - ); - const store = createStore(rootReducer, initialState, composedEnhancers); - if (process.env.NODE_ENV !== 'production' && module.hot) { - // console.log("hot reducer reload"); - module.hot.accept('../reducers', () => { - const nextRootReducer = require('../reducers/index'); - store.replaceReducer(nextRootReducer); - }); - } - return store; -}; - -export default configureStore; diff --git a/tsconfig.json b/tsconfig.json index a03dcf66c..37a8d7705 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ Visit https://aka.ms/tsconfig.json for a detailed list of options. /* Modules */ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - "types": ["node"], /* Specify type package names to be included without being referenced in a source file. */ + "types": ["node", "webpack-env"], /* Specify type package names to be included without being referenced in a source file. */ /* JavaScript Support */ "allowJs": true, /* Allow JavaScript files to be a part of your program. This allows TS files to import from JS files. */ @@ -44,6 +44,7 @@ Visit https://aka.ms/tsconfig.json for a detailed list of options. /* Completeness */ "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ }, "include": [ "src/**/*"