Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gvergnaud/ts-pattern
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v5.6.2
Choose a base ref
...
head repository: gvergnaud/ts-pattern
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 7 commits
  • 8 files changed
  • 3 contributors

Commits on Dec 18, 2024

  1. build(deps-dev): bump bun from 1.0.4 to 1.1.30 in /benchmarks

    Bumps [bun](https://github.com/oven-sh/bun) from 1.0.4 to 1.1.30.
    - [Release notes](https://github.com/oven-sh/bun/releases)
    - [Commits](oven-sh/bun@bun-v1.0.4...bun-v1.1.30)
    
    ---
    updated-dependencies:
    - dependency-name: bun
      dependency-type: direct:development
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Dec 18, 2024
    Copy the full SHA
    29e139e View commit details

Commits on Jan 21, 2025

  1. jsr: release 5.6.2

    gvergnaud committed Jan 21, 2025
    Copy the full SHA
    4d6c39b View commit details

Commits on Jan 25, 2025

  1. Merge pull request #303 from gvergnaud/dependabot/npm_and_yarn/benchm…

    …arks/bun-1.1.30
    
    build(deps-dev): bump bun from 1.0.4 to 1.1.30 in /benchmarks
    gvergnaud authored Jan 25, 2025
    Copy the full SHA
    fff3f1e View commit details

Commits on Feb 17, 2025

  1. Update README.md

    gvergnaud authored Feb 17, 2025
    Copy the full SHA
    4651f69 View commit details

Commits on Feb 22, 2025

  1. Copy the full SHA
    f1af270 View commit details

Commits on Feb 25, 2025

  1. Copy the full SHA
    d5d1bf2 View commit details

Commits on Feb 26, 2025

  1. Merge pull request #311 from gvergnaud/gvergnaud/improve-is-matching-…

    …predicate
    
    isMatching: improve narrowing
    gvergnaud authored Feb 26, 2025
    Copy the full SHA
    672b5ef View commit details
Showing with 86 additions and 44 deletions.
  1. +2 −2 README.md
  2. +60 −31 benchmarks/package-lock.json
  3. +1 −1 benchmarks/package.json
  4. +1 −1 jsr.json
  5. +2 −1 src/is-matching.ts
  6. +1 −1 src/patterns.ts
  7. +15 −1 tests/is-matching.test.ts
  8. +4 −6 tests/objects.test.ts
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -68,13 +68,13 @@ Read the introduction blog post: [Bringing Pattern Matching to TypeScript 🎨 I

Via npm

```
```sh
npm install ts-pattern
```

You can also use your favorite package manager:

```
```sh
pnpm add ts-pattern
# OR
yarn add ts-pattern
91 changes: 60 additions & 31 deletions benchmarks/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion benchmarks/package.json
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
"license": "ISC",
"devDependencies": {
"benny": "^3.7.1",
"bun": "^1.0.4",
"bun": "^1.1.30",
"ts-pattern": "^5.0.5"
}
}
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gabriel/ts-pattern",
"version": "5.6.1",
"version": "5.6.2",
"exports": {
".": "./src/index.ts",
"./types": "./src/index.ts",
3 changes: 2 additions & 1 deletion src/is-matching.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MatchedValue, Pattern, UnknownProperties } from './types/Pattern';
import * as P from './patterns';
import { matchPattern } from './internals/helpers';
import { WithDefault } from './types/helpers';

/**
* This constraint allows using additional properties
@@ -47,7 +48,7 @@ export function isMatching<const p extends Pattern<unknown>>(
export function isMatching<const T, const P extends PatternConstraint<T>>(
pattern: P,
value: T
): value is P.infer<P>;
): value is T & WithDefault<P.narrow<T, P>, P.infer<P>>;

export function isMatching<const p extends Pattern<any>>(
...args: [pattern: p, value?: any]
2 changes: 1 addition & 1 deletion src/patterns.ts
Original file line number Diff line number Diff line change
@@ -127,7 +127,7 @@ export type infer<pattern> = InvertPattern<NoInfer<pattern>, unknown>;
* type Narrowed = P.narrow<Input, typeof Pattern>
* // ^? ['a', 'a' | 'b']
*/
export type narrow<input, pattern extends Pattern<any>> = ExtractPreciseValue<
export type narrow<input, pattern> = ExtractPreciseValue<
input,
InvertPattern<pattern, input>
>;
16 changes: 15 additions & 1 deletion tests/is-matching.test.ts
Original file line number Diff line number Diff line change
@@ -137,7 +137,9 @@ describe('isMatching', () => {
expect(isMatching({ topping: 'cheese' }, food)).toBe(true);

if (isMatching({ topping: 'cheese' }, food)) {
type t = Expect<Equal<typeof food, Food & { topping: 'cheese' }>>;
type t = Expect<
Equal<typeof food, Pizza & { topping: 'cheese'; type: 'pizza' }>
>;
}
});

@@ -150,4 +152,16 @@ describe('isMatching', () => {
type t = Expect<Equal<typeof food, Food & { unknownProp: Error }>>;
}
});

it('should correctly narrow undiscriminated unions of objects.', () => {
type Input = { someProperty: string[] } | { this: 'is a string' };
const input = { someProperty: ['hello'] } satisfies Input as Input;

if (isMatching({ someProperty: P.array() }, input)) {
expect(input.someProperty).toEqual(['hello']);
type t = Expect<Equal<typeof input.someProperty, string[]>>;
} else {
throw new Error('pattern should match');
}
});
});
10 changes: 4 additions & 6 deletions tests/objects.test.ts
Original file line number Diff line number Diff line change
@@ -11,19 +11,17 @@ describe('Objects', () => {
it('should work with symbols', () => {
const fn1 = (obj: Input) => {
if (isMatching({ [symbolA]: { [symbolB]: 'foo' } }, obj)) {
type t = Expect<
Equal<typeof obj, { [symbolA]: { [symbolB]: 'foo' } }>
>;
const value = obj[symbolA][symbolB];
type t = Expect<Equal<typeof value, 'foo'>>;
} else {
throw new Error('Expected obj to match the foo pattern!');
}
};

const fn2 = (obj: Input) => {
if (isMatching({ [symbolA]: { [symbolB]: 'bar' } }, obj)) {
type t = Expect<
Equal<typeof obj, { [symbolA]: { [symbolB]: 'bar' } }>
>;
const value = obj[symbolA][symbolB];
type t = Expect<Equal<typeof value, 'bar'>>;
throw new Error('Expected obj to not match the bar pattern!');
}
};