Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(types): fix @netlify/headers-parser types #6104

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

serhalp
Copy link
Contributor

@serhalp serhalp commented Feb 25, 2025

Summary

fix @netlify/headers-parser types

These types were very weak, containing plentiful anys, both explicit and implicit, as well as some incorrect inferred types. This overhauls those types and fixes uncovered errors.

(This is needed to fix type errors in the CLI.)

simplify/fix tsconfig strict config

We should be opting into strict mode and only opting out of some flags incrementally while we fix errors. The current setup makes this difficult.

This PR:

  • flips the global strict flag on
  • removes values redundantly being set to the default
  • stops disabling flags that obscured no errors (or very few, which I then fixed)
  • moves a few flag disables to the specific packages that require them
  • explicitly configures strict flags for already rather strict packages (just edge-bundler, and now also headers-parser)

There's a lot more work to do here, but this is a start...

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib" /* Specify an output folder for all emitted files. */
"outDir": "lib" /* Specify an output folder for all emitted files. */,
"strictBindCallApply": false /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this down to this specific package so I could enable it in the base config

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib" /* Specify an output folder for all emitted files. */
"outDir": "lib" /* Specify an output folder for all emitted files. */,
"strictBindCallApply": false /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this down to this specific package so I could enable it in the base config

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib" /* Specify an output folder for all emitted files. */
"outDir": "lib" /* Specify an output folder for all emitted files. */,
"strictBindCallApply": false /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this down to this specific package so I could enable it in the base config

@@ -2,6 +2,8 @@ import { promises as fs } from 'fs'
import { basename, extname, dirname, join } from 'path'

import isPathInside from 'is-path-inside'
// @ts-expect-error(serhalp) -- Remove once https://github.com/schnittstabil/merge-options/pull/28 is merged, or replace
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seemed worthwhile, as it allowed enabling noImplicitAny in zisi

Comment on lines -6 to +14
"strict": true
"noImplicitAny": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"useUnknownInCatchVariables": false,
"exactOptionalPropertyTypes": false,
"noImplicitReturns": false,
"noUncheckedIndexedAccess": false,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": false
Copy link
Contributor Author

@serhalp serhalp Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent here was presumably to opt into strict mode, but the tsconfig files get merged on a field-by-field basis... so "strict": true here wasn't really doing anything, as the specific flags were all still disabled from the base config.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reenabled what I could but had to leave a few disabled 😞


import { pathExists } from 'path-exists'

import { splitResults } from './results.js'
import type { MinimalHeader } from './types.js'

type RawHeader = { path: string } | { name: string; value: string }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type RawHeader = { path: string } | { name: string; value: string }
type RawHeaderLine = { path: string } | { name: string; value: string }

@@ -3,6 +3,8 @@ import { mergeHeaders } from './merge.js'
import { parseConfigHeaders } from './netlify_config_parser.js'
import { normalizeHeaders } from './normalize.js'
import { splitResults, concatResults } from './results.js'
import type { Header, MinimalHeader } from './types.js'
export type { Header, MinimalHeader }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export type { Header, MinimalHeader }
export type { Header, MinimalHeader }

if (!Array.isArray(headers)) {
const error = new TypeError(`Headers must be an array not: ${headers}`)
return splitResults([error])
return splitResults<never>([error])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks funny but is correct: splitResults takes an array of T | Error and returns {values: T[]: errors: Error[]}; when given a literal array of type Error[] it can't infer T, so I explicitly pass in never as T.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this as an inline comment?

serhalp added a commit to netlify/cli that referenced this pull request Feb 27, 2025
These types were very weak, containing plentiful `any`s, both explicit and implicit, as
well as some incorrect inferred types.
We should be opting *into* strict mode and only opting *out* of some flags incrementally
while we fix errors.

This commit:
- flips the global `strict` on
- removes values being set to the default via the above
- stops disabling flags that obscured no errors (or very few, which I then fixed)
- moves a few flag disablings to the specific packages that require it
- explictly configures strict flags for already rather strict packages
@serhalp serhalp force-pushed the serhalp/cpla-2534-fix-all-generated-ts-expect-errors branch from f53fa6b to 1fa08ca Compare February 27, 2025 21:15
@serhalp serhalp marked this pull request as ready for review February 27, 2025 21:23
@serhalp serhalp requested a review from a team as a code owner February 27, 2025 21:23
Comment on lines +19 to +20
configHeaders: undefined | MinimalHeader[]
minimal: undefined | boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these two be optional?

const resultsArrays = await Promise.all(headersFiles.map(parseFileHeaders))
return concatResults(resultsArrays)
}

const getConfigHeaders = async function (netlifyConfigPath) {
const getConfigHeaders = async function (netlifyConfigPath?: undefined | string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const getConfigHeaders = async function (netlifyConfigPath?: undefined | string) {
const getConfigHeaders = async function (netlifyConfigPath?: string) {

undefined isn't required in optional parameters, even with exactOptionalPropertyTypes enabled. (I see this throughout the PR, but I'll just leave a single comment here.)

if (!Array.isArray(headers)) {
const error = new TypeError(`Headers must be an array not: ${headers}`)
return splitResults([error])
return splitResults<never>([error])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this as an inline comment?

serhalp added a commit to netlify/cli that referenced this pull request Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants