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

feat(assert): type narrowing for assertLess, assertLessOrEqual, asserGreater, assertGreaterOrEqual #6245

Closed
wants to merge 2 commits into from

Conversation

dandv
Copy link
Contributor

@dandv dandv commented Dec 9, 2024

  • disallow undefined actual values because any comparison with undefined returns false
  • disallow null expected values
  • narrow the returned type to exclude undefined
  • drive-by typo fix and relative path imports

Fixes #6244.

@dandv dandv requested a review from kt3k as a code owner December 9, 2024 06:17
@github-actions github-actions bot added the assert label Dec 9, 2024
Copy link

codecov bot commented Dec 9, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.49%. Comparing base (cc9a7c0) to head (80d9af5).
Report is 22 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6245   +/-   ##
=======================================
  Coverage   96.49%   96.49%           
=======================================
  Files         536      536           
  Lines       41179    41189   +10     
  Branches     6175     6178    +3     
=======================================
+ Hits        39735    39745   +10     
- Misses       1401     1402    +1     
+ Partials       43       42    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dandv dandv force-pushed the assert-type-narrowing branch from dd18100 to 79e9937 Compare December 9, 2024 06:20
@dandv
Copy link
Contributor Author

dandv commented Dec 9, 2024

On a second thought (after my #6244 issue), assertLess & friends should not accept undefined, because any comparison with undefined returns false.

If x can be undefined, any comparison with x, e.g. assert(x < 1), produces a Deno error that x is possibly undefined:

const x = Math.random() > 1.0 ? 10 : undefined;

console.log(x < 3);  // error: TS18048 [ERROR]: 'x' is possibly 'undefined'.

So I've added typing for these assertions to also expect actual to be any type except undefined.

actual: Exclude<T, undefined> | null,

The error isn't pretty, but it's better than nothing:

Argument of type 10 | undefined is not assignable to parameter of type 0 | 10 | null
Type undefined is not assignable to type 0 | 10 | null

The | null is there for explicitness, because comparison with null are valid (null gets coerced to zero). Removing it leads to slightly simpler errors:

Argument of type 10 | undefined is not assignable to parameter of type 0 | 10
Type undefined is not assignable to type 0 | 10

@@ -1,7 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
import { equal } from "./equal.ts";
import { format } from "@std/internal/format";
import { format } from "../internal/format.ts";
Copy link
Member

Choose a reason for hiding this comment

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

This relative import doesn't work when published to JSR as each package is published independently

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 made that change because the @std import led to this error when using the repo with file:/// imports from 3rd party code:

Relative import path "@std/internal/build-message" not prefixed with / or ./ or ../ and not in import map

Is there a syntax that would work in both cases, or should I revert the change from the first commit of this PR?

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 guess an import map in the 3rd party code would solve the problem. Feel free to cherry-pick / ignore the first commit.

Fixes error `Relative import path "@std/internal/build-message" not prefixed with / or ./ or ../ and not in import map`
when using the repo with file:/// import from 3rd party code
…rtGreaterOrEqual

- disallow undefined actual values because any comparison with undefined returns false
- disallow null expected values
- narrow the returned type to exclude undefined
@dandv dandv force-pushed the assert-type-narrowing branch from 78e5937 to 80d9af5 Compare December 15, 2024 08:35
@kt3k
Copy link
Member

kt3k commented Dec 19, 2024

This is a breaking change in the current format (The users will see the type error if the input type include undefined in its type), and we are not planning to make major version upgrade in the near future.

Also I don't see much value to this narrowing of types as the same effect can be achieved by calling assertExists(value) next line to these assertions.

@kt3k
Copy link
Member

kt3k commented Dec 24, 2024

We first need to discuss what can/should be done about this in #6244

Closing for now

@kt3k kt3k closed this Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

assertGreater, assertAlmostEquals, assertLess etc. don't do type narrowing
2 participants