Skip to content

Commit a85b10d

Browse files
36degreesowenatgov
authored andcommitted
Split component instantiation into separate function
TypeScript doesn’t really have the concept of passing a class to a function, so we have to fake it by defining a type that is constructable and has the properties we need to be able to instantiate it (a `moduleName` and optionally a set of `defaults` from which we can infer the config type). This is based on approaches from: - https://stackoverflow.com/questions/71086547/build-a-function-that-accepts-a-class-in-typescript - microsoft/TypeScript#17572 Co-authored-by: Owen Jones <[email protected]>
1 parent 3f313d8 commit a85b10d

File tree

1 file changed

+35
-13
lines changed
  • packages/govuk-frontend/src/govuk

1 file changed

+35
-13
lines changed

packages/govuk-frontend/src/govuk/init.mjs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,47 @@ function initAll(config) {
5050
const $scope = config.scope ?? document
5151

5252
components.forEach(([Component, config]) => {
53-
const $elements = $scope.querySelectorAll(
54-
`[data-module="${Component.moduleName}"]`
55-
)
53+
createAll(Component, config, $scope)
54+
})
55+
}
56+
57+
/**
58+
* @template {CompatibleClass} T
59+
* @param {T} Component - class of the component to create
60+
* @param {T["defaults"]} [config] - config for the component
61+
* @param {Element|Document} [$scope] - scope of the document to search within
62+
*/
63+
function createAll(Component, config, $scope = document) {
64+
const $elements = $scope.querySelectorAll(
65+
`[data-module="${Component.moduleName}"]`
66+
)
5667

57-
$elements.forEach(($element) => {
58-
try {
59-
// Only pass config to components that accept it
60-
'defaults' in Component
61-
? new Component($element, config)
62-
: new Component($element)
63-
} catch (error) {
64-
console.log(error)
65-
}
66-
})
68+
$elements.forEach(($element) => {
69+
try {
70+
// Only pass config to components that accept it
71+
'defaults' in Component
72+
? new Component($element, config)
73+
: new Component($element)
74+
} catch (error) {
75+
console.log(error)
76+
}
6777
})
6878
}
6979

7080
export { initAll }
7181

82+
/* eslint-disable jsdoc/valid-types --
83+
* `{new(...args: any[] ): object}` is not recognised as valid
84+
* https://github.com/gajus/eslint-plugin-jsdoc/issues/145#issuecomment-1308722878
85+
* https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/131
86+
**/
87+
88+
/**
89+
* @typedef {{new (...args: any[]): unknown, defaults?: object, moduleName: string}} CompatibleClass
90+
*/
91+
92+
/* eslint-enable jsdoc/valid-types */
93+
7294
/**
7395
* Config for all components via `initAll()`
7496
*

0 commit comments

Comments
 (0)