{"id":21507706,"url":"https://github.com/jsr-core/match","last_synced_at":"2025-04-09T15:50:21.247Z","repository":{"id":225853066,"uuid":"766854228","full_name":"jsr-core/match","owner":"jsr-core","description":"A **true** pattern matching library for JavaScript/ TypeScript","archived":false,"fork":false,"pushed_at":"2024-04-22T03:40:31.000Z","size":91,"stargazers_count":42,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-23T18:04:37.028Z","etag":null,"topics":["javascript","jsr","pattern-matching","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsr-core.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-03-04T08:54:50.000Z","updated_at":"2025-02-24T03:19:55.000Z","dependencies_parsed_at":"2024-04-06T08:45:49.877Z","dependency_job_id":null,"html_url":"https://github.com/jsr-core/match","commit_stats":null,"previous_names":["tani/ts-match","jsr-core/match"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsr-core%2Fmatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsr-core%2Fmatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsr-core%2Fmatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsr-core%2Fmatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsr-core","download_url":"https://codeload.github.com/jsr-core/match/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248063783,"owners_count":21041853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","jsr","pattern-matching","typescript"],"created_at":"2024-11-23T20:38:05.342Z","updated_at":"2025-04-09T15:50:21.215Z","avatar_url":"https://github.com/jsr-core.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![@core/match](https://typography.deno.dev/render?text=%40core%2Fmatch\u0026family=Poiret+One\u0026weight=400\u0026size=50\u0026color=%23ff8040)\n\n\\[ [GitHub tani/ts-match](https://github.com/tani/ts-match) \\] \\[ [JSR @core/match](https://jsr.io/@core/match) \\]\n\nA pattern matching library for JavaScript/ TypeScript\n\nEcmaScript has a structured binding. It is a very useful notation for extracting\nonly the necessary parts from a complex structure. However, this structured\nbinding is incomplete for use as pattern matching. Because, To do a structured\nbinding, the pre-assigned value must match the pattern, If it does not match the\npattern, an exception is thrown.\n\n```ts\nconst { a } = JSON.parse(\"null\"); // ERROR!\n```\n\nTherefore, to do structured binding, TypeScript either guarantees that the\nstructure matches at compile time, or it does not, validation libraries such as\nzod or unknownutil checks at runtime that the structure matches. The former is\nimpotent for data whose structure is not determined at compile time, such as\nJSON data. The latter required writing two structured binding patterns and two\nvalidation patterns.\n\n**This library can perform structured binding and validation simultaneously, while\npreserving compile-time type information.** It is a library that enables true\npattern matching and brings EcmaScript's structured binding to perfection.\n\nAgain, this is not just for TypeScript, it is also useful in JavaScript.\n\n## Usage\n\nThis library is published in JSR and can be used in Deno with `jsr:@core/match`.\nThere are only two functions that users need to remember: `_` and `match`.\n\n```ts\nimport { match, placeholder as _ } from \"jsr:@core/match\";\n```\n\n- `_` is a function for creating structured bound patterns. If you already use\n  `_` for other library, you can use other name like `__`.\n\n  ```ts\n  const pattern = {\n    name: _(\"name\"), // this value will be captured as unknown value\n    address: {\n      country: _(\"country\"), // you can write the placeholder anywhere,.\n      state: \"NY\", // without place holder, matcher will compares the values using ===\n    },\n    age: _(\"age\", isNumber), // you can specify the type of placeholder with the type guard,\n    favorites: [\"baseball\", _(\"favorite\")], // you can put the placeholder in an array\n    others: [_(1), _(Symbol.other)], // you can declare the placeholder with number or symbol\n    message: _`Hello, ${_(\"nickname\")}` // you can put the placeholder in the template string.\n  };\n  ```\n\n- `match` is a function for performing structured binding. If you execute a\n  structured binding based on the above pattern, the value corresponding to the\n  following `Match` type is:\n  - an object whose key is the name declared as placeholder, and\n  - the placeholder given the type guard will be of that type, and\n  - if the structure does not match or the type guard fails, `undefined` is\n    returned.\n\n  ```ts\n  type Match = {\n    [1]: unknown,\n    [Symbol.other]: unknown\n    name: unknown,\n    country: unknown,\n    age: number,\n    favorite: unknown,\n    nickname: string\n  } | undefined;.\n  const result: Match = match(pattern, value);\n  ```\n\n## How to declare type guards.\n\nIn TypeScript, a type guard is a function with type `(v: unknown) =\u003e v is T`, It\ncan be declared as follows. There is also a collection of generic type guards,\nsuch as unknownutil.\n\n```ts\nfunction isNumber(v: unknown): v is number {\n  return typeof v === \"number\";\n}\n```\n\n## License.\n\nThis library is licensed under the MIT License. Please feel free to use it as\nlong as you comply with the licence.\n\n---\n\n## Scenarios for using this library\n\nFirst, load the library.\n\n```ts\nimport { match, placeholder as _ } from \"./mod.ts\";\nimport { assertEquals } from \"jsr:@std/assert\";\n```\n\nThis library can be used to check if an object matches a specific pattern. The\nfollowing example demonstrates how to match an object with a simple string\nvalue. If the object matches the pattern, the result will be an empty object,\nsince the pattern does not contain any placeholders yet.\n\n```ts\nDeno.test(\"match object with primitive string value\", () =\u003e {\n  const pattern = \"hello\";\n  const value = \"hello\";\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nYou can also use numeric values as patterns.\n\n```ts\nDeno.test(\"match object with primitive number value\", () =\u003e {\n  const pattern = 123;\n  const value = 123;\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nBoolean values also can be used as patterns.\n\n```ts\nDeno.test(\"match object with primitive boolean value\", () =\u003e {\n  const pattern = true;\n  const value = true;\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nNull values can be used as patterns as well. Note that the match function\nreturns an empty object even if both the pattern and the value are null.\n\n```ts\nDeno.test(\"match object with primitive null value\", () =\u003e {\n  const pattern = null;\n  const value = null;\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nUndefined values can also be used as patterns. Note that the match function\nreturns an empty object even if both the pattern and the value are undefined.\n\n```ts\nDeno.test(\"match object with primitive undefined value\", () =\u003e {\n  const pattern = undefined;\n  const value = undefined;\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nSymbol values can be used as patterns as well.\n\n```ts\nDeno.test(\"match object with primitive symbol value\", () =\u003e {\n  const symbol = Symbol(\"hello\");\n  const pattern = symbol;\n  const value = symbol;\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nYou can also use compound objects as patterns. If the object matches the\npattern, the result will still be an empty object, because there are no\nplaceholders in the pattern.\n\n```ts\nDeno.test(\"match object with compound object value\", () =\u003e {\n  const pattern = { name: \"hello\", age: 1 };\n  const value = { name: \"hello\", age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nArrays can be used as patterns too. If the object matches the pattern, the\nresult will still be an empty object, because there are no placeholders in the\npattern.\n\n```ts\nDeno.test(\"match object with array value\", () =\u003e {\n  const pattern = [\"hello\", 123];\n  const value = [\"hello\", 123];\n  const result = match(pattern, value);\n  assertEquals(result, {});\n});\n```\n\nIf the object does not match the pattern, the match function returns undefined.\nIn the following pattern, the value of the object does not match the pattern\nbecause the value is not object.\n\n```ts\nDeno.test(\"match object with primitive value (not equal)\", () =\u003e {\n  const pattern = { a: 1 };\n  const value = 123;\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nNow, let's use a placeholder. The first step is to declare a single placeholder.\nThe placeholder is declared using the `_` function, and the name of the\nplaceholder is passed as an argument. The placeholder holds the name's string\nvalue and the type guard function `test`. The following placeholder does not\nhave a type guard, making it the simplest form of a placeholder.\n\n```ts\nDeno.test(\"declare single placeholder\", () =\u003e {\n  const pattern = _(\"a\");\n  assertEquals(pattern.name, \"a\");\n  assertEquals(pattern.test, undefined);\n});\n```\n\nTo use the placeholder, apply the match function. The match function returns an\nobject containing the key-value pair of the placeholder's name and the\nassociated object's value. If the object does not match the pattern, the match\nfunction returns undefined. Note that the resulting object has an `a` key, the\nvalue of the object is `hello`, and its type is `unknown` in TypeScript because\nthe placeholder has no type guard.\n\n```ts\nDeno.test(\"match object with single placeholder\", () =\u003e {\n  const pattern = _(\"a\");\n  const value = \"hello\";\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\" });\n});\n```\n\nTo provide a type guard for the placeholder, declare the type guard function as\nthe second argument of the `_` function.\n\n```ts\nDeno.test(\"match object with single placeholder and type guard\", () =\u003e {\n  const pattern = _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\");\n  const value = \"hello\";\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\" });\n});\n```\n\nIf the type guard fails, the match function returns undefined.\n\n```ts\nDeno.test(\"match object with single placeholder and type guard\", () =\u003e {\n  const pattern = _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\");\n  const value = 123;\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nPlaceholders can also be used in compound objects. The following pattern has two\nplaceholders, `a` and `b`. Note that the resulting object has `a` and `b` keys,\nand the values of the object are `hello` and `123` respectively. Furthermore,\nthe type of the `a` value is `unknown`, and the type of the `b` value is\n`unknown` in TypeScript.\n\n```ts\nDeno.test(\"match object with compound object and placeholders\", () =\u003e {\n  const pattern = { name: _(\"a\"), age: _(\"b\") };\n  const value = { name: \"hello\", age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 1 });\n});\n```\n\nSimilarly, you can pass the type guard to the placeholder. In this case, the\ntype of the `a` value is `string`, while the type of the `b` value is `number`\nin TypeScript.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (type guard)\", () =\u003e {\n  const pattern = {\n    name: _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: _(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  };\n  const value = { name: \"hello\", age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 1 });\n});\n```\n\nIt is expected that the match function returns undefined if the object does not\nmatch the pattern. In the following pattern, there are two placeholders, `a` and\n`b`. The value of the object does not match the pattern because the `name` key\nis missing. Therefore, the match function returns undefined.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (missing key)\", () =\u003e {\n  const pattern = { name: _(\"a\"), age: _(\"b\") };\n  const value = { age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nYou can also use the placeholder to skip the key. The following pattern has two\nplaceholders, anonymous placeholder and `b`. Note that the resulting object has\nonly `b` key, and the value of the object is `1`. Furthermore, the type of the\n`b` value is `unknown` in TypeScript because the placeholder has no type guard.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (skip key)\", () =\u003e {\n  const pattern = { name: _(), age: _(\"b\") };\n  const value = { name: \"john\", age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, { b: 1 });\n});\n```\n\nAs the same as other cases, the anonymous placeholder can be used with the type\nguard. The following pattern has two placeholders, anonymous placeholder and\n`b`. Note that the resulting object has only `b` key, and the value of the\nobject is `1`. Furthermore, the type of the `b` value is `unknown` in TypeScript\nbecause the placeholder has no type guard.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (skip key, type guard)\", () =\u003e {\n  const pattern = {\n    name: _((v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: _(\"b\"),\n  };\n  const value = { name: \"john\", age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, { b: 1 });\n});\n```\n\nThe match function returns undefined if the object does not match the pattern.\nThe following pattern has two placeholders, anonymous placeholder and `b`. The\nvalue of the object does not match the pattern because the type guard fails.\nTherefore, the match function returns undefined.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (skip key, type guard, fail)\", () =\u003e {\n  const pattern = {\n    name: _((v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: _(\"b\"),\n  };\n  const value = { name: 1, age: 1 };\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nIn other cases, the match function returns undefined if the type guard fails.\nThe following pattern has two placeholders, `a` and `b`. The value of the object\ndoes not match the pattern because the `age` value is not a number. Therefore,\nthe match function returns undefined.\n\n```ts\nDeno.test(\"match object with compound object and placeholders (type guard fail)\", () =\u003e {\n  const pattern = {\n    name: _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: _(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  };\n  const value = { name: \"hello\", age: \"123\" };\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nPlaceholders can be used in arrays as well. The following pattern has two\nplaceholders, `a` and `b`. Note that the resulting object has `a` and `b` keys,\nand the values of the object are `hello` and `123` respectively. Furthermore,\nthe type of the `a` value is `unknown`, and the type of the `b` value is\n`unknown` in TypeScript.\n\n```ts\nDeno.test(\"match object with array and placeholders\", () =\u003e {\n  const pattern = [_(\"a\"), _(\"b\")];\n  const value = [\"hello\", 123];\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 123 });\n});\n```\n\nYou can pass the type guard to the placeholder in the same way as before, so the\ntype of the `a` value is `string`, and the type of the `b` value is `number` in\nTypeScript.\n\n```ts\nDeno.test(\"match object with array and placeholders (type guard)\", () =\u003e {\n  const pattern = [\n    _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    _(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  ];\n  const value = [\"hello\", 123];\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 123 });\n});\n```\n\nIt is expected that the match function returns undefined if the object does not\nmatch the pattern. The following pattern has two placeholders, `a` and `b`. The\nvalue of the object does not match the pattern because the `name` key is\nmissing.\n\n```ts\nDeno.test(\"match object with array and placeholders (missing key)\", () =\u003e {\n  const pattern = [_(\"a\"), _(\"b\")];\n  const value = [123];\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nIn other cases, the match function returns undefined if the type guard fails.\nThe following pattern has two placeholders, `a` and `b`. The value of the object\ndoes not match the pattern because the `age` value is not a number.\n\n```ts\nDeno.test(\"match object with array and placeholders (type guard fail)\", () =\u003e {\n  const pattern = [\n    _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    _(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  ];\n  const value = [\"hello\", \"123\"];\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nPlaceholders can be used in both objects and arrays at the same time. The\nfollowing pattern has two placeholders, `a` and `b`. Note that the resulting\nobject has `a` and `b` keys, and the values of the object are `hello` and `123`\nrespectively. Furthermore, the type of the `a` value is `unknown`, and the type\nof the `b` value is `unknown` in TypeScript.\n\n```ts\nDeno.test(\"match object with object, array, and placeholders\", () =\u003e {\n  const pattern = { name: _(\"a\"), age: [_(\"b\")] };\n  const value = { name: \"hello\", age: [123] };\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 123 });\n});\n```\n\nIn the same manner, you can pass the type guard to the placeholder. Now, the\ntype of the `a` value is `string`, and the type of the `b` value is `number` in\nTypeScript.\n\n```ts\nDeno.test(\"match object with object, array, and placeholders (type guard)\", () =\u003e {\n  const pattern = {\n    name: _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: [_(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\")],\n  };\n  const value = { name: \"hello\", age: [123] };\n  const result = match(pattern, value);\n  assertEquals(result, { a: \"hello\", b: 123 });\n});\n```\n\nIt is expected that the match function will return undefined if the object does\nnot match the pattern. In the following pattern, there are two placeholders, `a`\nand `b`. The value of the object does not match the pattern because the `name`\nkey is missing.\n\n```ts\nDeno.test(\"match object with object, array, and placeholders (missing key)\", () =\u003e {\n  const pattern = { name: _(\"a\"), age: [_(\"b\")] };\n  const value = { age: [123] };\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nIn other cases, the match function returns undefined if the type guard fails.\nThe following pattern has two placeholders, `a` and `b`. The value of the object\ndoes not match the pattern because the `age` value is not a number.\n\n```ts\nDeno.test(\"match object with object, array, and placeholders (type guard fail)\", () =\u003e {\n  const pattern = {\n    name: _(\"a\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: [_(\"b\", (v: unknown): v is number =\u003e typeof v === \"number\")],\n  };\n  const value = { name: \"hello\", age: [\"123\"] };\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nAs a niche feature, pattern matching with placeholders can be used with\nuser-defined classes. Note that the resulting object has `name` and `age` keys,\nand the values of the object are `hello` and `123` respectively. Furthermore,\nthe type of the `name` value is `unknown`, and the type of the `age` value is\n`number` in TypeScript because the placeholder has no type guard for the `name`\nvalue.\n\n```ts\nclass User {\n  name: string;\n  age: number;\n  constructor(name: string, age: number) {\n    this.name = name;\n    this.age = age;\n  }\n}\nDeno.test(\"match object with user-defined class and placeholders\", () =\u003e {\n  const pattern = {\n    name: _(\"name\"),\n    age: _(\"age\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  };\n  const value = new User(\"hello\", 123);\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"hello\", age: 123 });\n});\n```\n\nIn the same manner, you can pass the type guard to the placeholder. Now, the\ntype of the `name` value is `string`, and the type of the `age` value is\n`number` in TypeScript.\n\n```ts\nDeno.test(\"match object with user-defined class and placeholders (type guard)\", () =\u003e {\n  const pattern = {\n    name: _(\"name\", (v: unknown): v is string =\u003e typeof v === \"string\"),\n    age: _(\"age\", (v: unknown): v is number =\u003e typeof v === \"number\"),\n  };\n  const value = new User(\"hello\", 123);\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"hello\", age: 123 });\n});\n```\n\nIt is expected that the match function will return undefined if the object does\nnot match the pattern. In the following pattern, there are two placeholders,\n`name` and `age`. The value of the object does not match the pattern because the\n`name` key is missing.\n\n```ts\nDeno.test(\"match object with user-defined class and placeholders (missing key)\", () =\u003e {\n  const pattern = { name: _(\"name\"), age: _(\"age\") };\n  const value = new User(\"hello\", 123);\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"hello\", age: 123 });\n});\n```\n\nAdditionally, if the pattern is not a direct instance of an `Object` or an\n`Array`, the match function tries to check the equality of the pattern and the\nvalue using the `===` operator. Hence, the following pattern does not match the\nvalue, and the match function returns undefined.\n\n```ts\nDeno.test(\"match object with primitive string value (not equal)\", () =\u003e {\n  const pattern = new User(\"hello\", 123);\n  const value = new User(\"hello\", 123);\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nThe match function also supports template string placeholders. The following\npattern has a template string placeholder, `name`. Note that the resulting\nobject has a `name` key, and the value of the object is `john`. The type of the\n`name` value is `string` in TypeScript because the placeholder has no type\nguard.\n\n```ts\nDeno.test(\"match object with template string placeholder\", () =\u003e {\n  const pattern = _`hello ${_(\"name\")}`;\n  const value = \"hello john\";\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"john\" });\n});\n```\n\nYou can also pass the type guard to the placeholder in the same way as before.\nNow, the type of the `name` value is `string` in TypeScript.\n\n```ts\nDeno.test(\"match object with template string placeholder (type guard)\", () =\u003e {\n  const pattern = _`hello ${\n    _(\"name\", (v: unknown): v is string =\u003e typeof v === \"string\")\n  }`;\n  const value = \"hello john\";\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"john\" });\n});\n```\n\nThe match function returns undefined if the object does not match the pattern.\nThe following pattern has a template string placeholder, `answer`. The value of\nthe object does not match the pattern because the value is not a number.\n\n```ts\nDeno.test(\"match object with template string placeholder (type guard, fail)\", () =\u003e {\n  const isNumString = (v: unknown): v is `${number}` =\u003e\n    typeof v === \"string\" \u0026\u0026 !isNaN(Number(v));\n  const pattern = _`1 + 1 = ${_(\"answer\", isNumString)}`;\n  const value = \"1 + 1 = infinity\";\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nThe positive case of the type guard is also tested. The following pattern has a\ntemplate string placeholder, `answer`. The value of the object matches the\npattern, and the match function returns an object containing the key-value pair\nof the placeholder's name and the associated object's value. Note that the\nresulting object has an `answer` key, and the value of the object is `2`. The\ntype of the `answer` value is `'${numver}'`, which is a string shape of a number\nin TypeScript.\n\n```ts\nDeno.test(\"match object with template string placeholder (type guard)\", () =\u003e {\n  const isNumString = (v: unknown): v is `${number}` =\u003e\n    typeof v === \"string\" \u0026\u0026 !isNaN(Number(v));\n  const pattern = _`1 + 1 = ${_(\"answer\", isNumString)}`;\n  const value = \"1 + 1 = 2\";\n  const result = match(pattern, value);\n  assertEquals(result, { answer: \"2\" });\n});\n```\n\nIt is expected that the match function will return undefined if the object does\nnot match the pattern. In the following pattern, there is a template string\nplaceholder, `name`. The value of the object does not match the pattern because\nthe length of the value is not equal to the length of the pattern.\n\n```ts\nDeno.test(\"match object with template string placeholder (length not match)\", () =\u003e {\n  const pattern = _`hello ${_(\"name\")}`;\n  const value = \"hello\";\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nIn other cases, the match function returns undefined. The following pattern has\na template string placeholder, `name`. The value of the object does not match\nthe pattern because the value is not a string.\n\n```ts\nDeno.test(\"match object with template string placeholder (not string)\", () =\u003e {\n  const pattern = _`hello ${_(\"name\")}`;\n  const value = 123;\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nThe match function also supports template string placeholders with multiple\nplaceholders. The following pattern has two template string placeholders, `name`\nand `age`. Note that the resulting object has `name` and `age` keys, and the\nvalues of the object are `john` and `123` respectively. The type of the `name`\nvalue is `string`, and the type of the `age` value is `string` in TypeScript\nbecause the placeholders have no type guards.\n\n```ts\nDeno.test(\"match object with template string placeholder with multiple placeholders\", () =\u003e {\n  const pattern = _`${_(\"name\")} is ${_(\"age\")} years old`;\n  const value = \"john is 123 years old\";\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"john\", age: \"123\" });\n});\n```\n\nMatch funciton returns undefined if the object does not match the pattern. The\nfollowing pattern has two template string placeholders, `name` and `age`. The\nvalue of the object does not match the pattern because the value is shorter than\nthe pattern.\n\n```ts\nDeno.test(\"match object with template string placeholder with multiple placeholders (not equal)\", () =\u003e {\n  const pattern = _`${_(\"name\")} is ${_(\"age\")} years old`;\n  const value = \"john is 123 years\";\n  const result = match(pattern, value);\n  assertEquals(result, undefined);\n});\n```\n\nThe match function also supports template string placeholders with greedy mode.\nThe following pattern has two template string placeholders, `name` and `age`.\nNote that the resulting object has `name` and `age` keys, and the values of the\nobject are `john` and `123` respectively. The type of the `name` value is\n`string`, and the type of the `age` value is `string` in TypeScript because\nthe placeholders have no type guards.\n\n```ts\nDeno.test(\"match object with template string placeholder with multiple placeholders (greedy, not equal)\", () =\u003e {\n  const pattern = _.greedy`${_(\"name\")} is ${_(\"age\")} years old`;\n  const value = \"john is 123 years old\";\n  const result = match(pattern, value);\n  assertEquals(result, { name: \"john\", age: \"123\" });\n});\n```\n\nUltimately, the match function could run with a pattern that contains a regular\nplaceholder and a template string placeholder. The following pattern has a\nregular placeholder, `address`, and a template string placeholder, `message`.\nNote that the resulting object has `address`, `name`, and `age` keys, and the\nvalues of the object are `123`, `john`, and `123` respectively. The type of the\n`address` value is `string`, and the type of the `name` and `age` values are\n`string` in TypeScript because the placeholders have no type guards.\n\n```ts\nDeno.test(\"match object with a regular placeholder with the template string placeholder\", () =\u003e {\n  const pattern = {\n    address: _(\"address\"),\n    message: _`${_(\"name\")} is ${_(\"age\")} years old`,\n  };\n  const value = {\n    address: \"123\",\n    message: \"john is 123 years old\",\n  };\n  const result = match(pattern, value);\n  assertEquals(result, { address: \"123\", name: \"john\", age: \"123\" });\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsr-core%2Fmatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsr-core%2Fmatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsr-core%2Fmatch/lists"}