Full Code of modfy/nominal for AI

master 00faaf156930 cached
14 files
17.4 KB
4.9k tokens
23 symbols
1 requests
Download .txt
Repository: modfy/nominal
Branch: master
Commit: 00faaf156930
Files: 14
Total size: 17.4 KB

Directory structure:
gitextract_m2ssrx3h/

├── .gitignore
├── .vscode/
│   └── settings.json
├── Readme.md
├── examples/
│   ├── basic.ts
│   ├── composing.ts
│   ├── proportionalityConstant.ts
│   ├── safeRecord.ts
│   └── sort.ts
├── package.json
├── rome.json
├── src/
│   ├── index.ts
│   ├── proportionalityConstant.ts
│   └── standardLib.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
node_modules

================================================
FILE: .vscode/settings.json
================================================
{
  "[typescriptreact]": {
    "editor.defaultFormatter": "rome.rome"
  },
  "[typescript]": {
    "editor.defaultFormatter": "rome.rome"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}


================================================
FILE: Readme.md
================================================
# Nominal
The right way to do types in typescript.

## Installation

```bash
npm install nominal-types

yarn install nominal-types

pnpm install nominal-types
```

# Usage

## Basic
The most immediate benefit of nominal types is preventing confusion between two types. In regular Typescript 
you run into this problem:
```ts
type Minutes = number
type Seconds = number
const minutesToSeconds = (minutes: Minutes) => minutes * 60

const seconds: Seconds = 420
// uh-oh, we can use Minutes and Seconds interchangeably
minutesToSeconds(seconds)
```

Nominal types solve this problem
```ts
import { Nominal, nominal } from 'nominal-types';

type Minutes = Nominal<'Minutes', number>;
type Seconds = Nominal<'Seconds', number>;

const minutesToSeconds = (minutes: Minutes) => minutes * 60

// You can directly type cast or use nominal.make
const seconds = nominal.make<Seconds>(420)
const minutes = 1337 as Minutes

// doesn't work, yay type safety
minutesToSeconds(seconds)
// does work!
minutesToSeconds(minutes)
```

## Another example
You can use nominal types to give your code even better type-safety guarantees. 

This goes **beyond just type-safety**, it's a performance optimization: once you know the array is sorted, you never have to sort it again. This is enforcing that at a type level.


```typescript
type SortedArray<T> = Nominal<'sortedArray', Array<T>>

const sort = <T>(arr: Array<T>): SortedArray<T> => arr.sort()

const binarySearch = <T>(
  sorted: SortedArray<T>,
  search: T
): number | undefined  => {
    /* ... */
}

const regularArray = [1, 7, 2, 3, 6, 9, 10, 4, 5]
// won't work
binarySearch(regularArray, 2)
// will work
binarySearch(sort(regularArray), 3)
```

This is also known as [Refinement types](https://en.wikipedia.org/wiki/Refinement_type)



## Composing types

We can actually make this a bit crazier, we can compose nominal types

```ts

type SortedArray<T> = Nominal<'sortedArray', Array<T>>

const sort = <T>(arr: Array<T>): SortedArray<T> => arr.sort() as SortedArray<T>

const nonEmpty = <T>(arr:Array<T>):NonEmptyArray<T> => arr.filter(Boolean) as NonEmptyArray<T>

type NonEmptyArray<K, T extends Array<K>> = Nominal<'nonEmptyArray', T>;
type NonEmptySorted<T> = NonEmptyArray<T, SortedArray<T>>;

const binarySearch = <T>(sorted: NonEmptySorted<T>): T => {
  let foo = sorted[0]
  return foo
}

// won't work
binarySearch(regularArray)
// still won't work
binarySearch(sort(regularArray))

binarySearch(nonEmpty(sort(regularArray)))

```

## Examples

More examples in [examples folder](./examples), you can also see them typed on replit.

| Example     | Link                                                      |
|-------------|-----------------------------------------------------------|
| basic       |    https://replit.com/@CryogenicPlanet/Nominal#basic.ts   |
| sorting     |    https://replit.com/@CryogenicPlanet/Nominal#sort.ts    |
| composing   | https://replit.com/@CryogenicPlanet/Nominal#composing.ts  |
| safeRecords | https://replit.com/@CryogenicPlanet/Nominal#safeRecord.ts |

## Credits

You can read more about this https://zackoverflow.dev/writing/nominal-and-refinement-types-typescript

Inspiration from [Ghosts of Departed Proofs (Functional Pearl)](https://kataskeue.com/gdp.pdf)

================================================
FILE: examples/basic.ts
================================================
// After Nominal
import { Nominal } from '../src';
import { Equal, Expect } from '@type-challenges/utils';

type Minutes = Nominal<'Minutes', number>;
type Seconds = Nominal<'Seconds', number>;

const minutesToSeconds = (minutes: Minutes): Seconds =>
  (minutes * 60) as Seconds;

// You can directly type cast or use nominal.make
const seconds = 420 as Seconds;
const minutes = 1337 as Minutes;

// @ts-expect-error - doesn't work, yay type safety
minutesToSeconds(seconds);

// does work!
minutesToSeconds(minutes);

// @ts-expect-error -  won't work, yay!
minutesToSeconds(minutesToSeconds(minutes));


================================================
FILE: examples/composing.ts
================================================
import { Nominal } from '../src';

type SortedArray<T> = Nominal<'sortedArray', T[]>;

const sort = <T>(arr: T[]): SortedArray<T> => arr.sort() as SortedArray<T>;

const nonEmpty = <K, T extends K[]>(arr: T): NonEmptyArray<K, T> => {
  if (arr.length === 0) {
    throw new Error('Array is empty');
  }
  return arr as NonEmptyArray<K, T>;
};

type NonEmptyArray<K, T extends K[]> = Nominal<'nonEmptyArray', T>;
type NonEmptySorted<T> = NonEmptyArray<T, SortedArray<T>>;

// Not implemented
const binarySearch = <T>(sorted: NonEmptySorted<T>): T => {
  let foo = sorted[0];
  // @ts-ignore
  return foo;
};

const regularArray = [1, 2, 3];

// @ts-expect-error - won't work
binarySearch(regularArray);
// @ts-expect-error - still won't work
binarySearch(sort(regularArray));

// will work
binarySearch(nonEmpty(sort(regularArray)));


================================================
FILE: examples/proportionalityConstant.ts
================================================
import { Equal, Expect } from '@type-challenges/utils';

import {
  divideWithK,
  multiplyWithK,
  Nominal,
  ProportionalityConstant,
} from '../src';

export type Pixel = Nominal<'Pixel', number>;
export type Seconds = Nominal<'Seconds', number>;
export type PixelPerSecond = ProportionalityConstant<Pixel, Seconds>;

const PIXEL_PER_SECOND: PixelPerSecond = 1 as PixelPerSecond;

const pixels = 100 as Pixel;
const seconds = 1 as Seconds;

const a = multiplyWithK(PIXEL_PER_SECOND, seconds);
type A = typeof a;

// @ts-expect-error - should not be able to divide with seconds
const _b = divideWithK(PIXEL_PER_SECOND, seconds);

const c = divideWithK(PIXEL_PER_SECOND, pixels);
type C = typeof c;

type _cases = [Expect<Equal<A, Pixel>>, Expect<Equal<C, Seconds>>];


================================================
FILE: examples/safeRecord.ts
================================================
import { Nominal } from '../src';

type SafeRecord<V, R extends string = ''> = Nominal<
  'safeRecordSymbol',
  Record<R, V>
>;

const newRecord = <Value extends any, Record extends string>(
  record: Record,
  value: Value,
): SafeRecord<Value, Record> =>
  ({ [record]: value }) as SafeRecord<Value, Record>;

const add = <V, R extends string, R2 extends string>(
  record: SafeRecord<V, R>,
  key: R2,
  value: V,
): SafeRecord<V, R | R2> => {
  Object.assign(record, { [key]: value });

  return record as SafeRecord<V, R | R2>;
};

const safeRecord = newRecord('a', 'b');

// @ts-expect-error -  Won't work
const x = safeRecord['random']; // any

const lmao = add(safeRecord, 'lmao', 'nice');

lmao.a; // string
lmao.lmao; // string

// @ts-expect-error -  Won't work
lmao['random']; // any -  Untyped


================================================
FILE: examples/sort.ts
================================================
import { Nominal } from '../src';

type SortedArray<T> = Nominal<'sortedArray', T[]>;

const sort = <T>(arr: T[]): SortedArray<T> => arr.sort() as SortedArray<T>;

const binarySearch = <T>(
  sorted: SortedArray<T>,
  search: T,
): number | undefined => {
  if (sorted.length !== 0) {
    const midPoint = sorted.length / 2;
    if (sorted[midPoint] === search) {
      return midPoint;
    }

    // Bang: Midpoint will exist
    if (search > sorted[midPoint]!) {
      return binarySearch(sorted.slice(midPoint) as SortedArray<T>, search);
    } else {
      return binarySearch(sorted.slice(0, midPoint) as SortedArray<T>, search);
    }
  } else {
    return undefined;
  }
};

const regularArray = [1, 7, 2, 3, 6, 9, 10, 4, 5];
// @ts-expect-error  won't work
binarySearch(regularArray, 2);
// will work
binarySearch(sort(regularArray), 2);


================================================
FILE: package.json
================================================
{
  "name": "nominal-types",
  "version": "0.2.0",
  "description": "Nominal types for better typesafety",
  "main": "src/index.ts",
  "types": "src/index.ts",
  "keywords": [
    "nominal",
    "typesafety",
    "custom",
    "ids"
  ],
  "author": "modfy",
  "license": "MIT",
  "files": [
    "src/"
  ],
  "devDependencies": {
    "@type-challenges/utils": "^0.1.1",
    "rome": "^10.0.1",
    "typescript": "^5.0.2"
  }
}


================================================
FILE: rome.json
================================================
{
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space"
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single"
    }
  }
}


================================================
FILE: src/index.ts
================================================
const M = Symbol();

export type Nominal<Name extends string, Type> = Type & {
  readonly [M]: [Name];
};

export * from './standardLib';
export * from './proportionalityConstant';


================================================
FILE: src/proportionalityConstant.ts
================================================
// export type xPERy<X, Y> =

/**
 * ProportionalityConstant is a type that represents a constant that is used to convert from one type to another
 *
 * Y ∝ X -> Y = λX >  =kX
 *
 * This type is the type of the constant k in the above equation, it can used with the multiplyWithK and divideWithK functions to convert between the two types
 *
 * @example type PixelPerSecond = ProportionalityConstant<Pixel, Seconds>
 *
 * const pixels: Pixels = multiplyWithK(PIXEL_PER_SECOND, 1 as Seconds)
 *
 * const seconds: Seconds = divideWithK(PIXEL_PER_SECOND, 1 as Pixels)
 *
 */
export type ProportionalityConstant<
  Y extends number,
  X extends number,
> = number & {
  readonly __X: X;
  readonly __Y: Y;
};

type multiplyWithKReturn<K> = K extends ProportionalityConstant<
  infer Y,
  infer _X
>
  ? Y
  : never;

type multiplyWithKInferX<K> = K extends ProportionalityConstant<
  infer _Y,
  infer X
>
  ? X
  : never;

type divideWithKReturn<K> = K extends ProportionalityConstant<infer _Y, infer X>
  ? X
  : never;

type divideWithKInferY<K> = K extends ProportionalityConstant<infer Y, infer _X>
  ? Y
  : never;

/**
 * A function to get the converted typed after multiplying with proportionality constant
 *
 * @param k - ProportionalityConstant<Y,X> -> Y ∝ X -> Y = λX -> Y = kX
 * @param x - Value of type X
 * @returns y - Value of type Y
 */
export const multiplyWithK = <K extends number>(
  k: K,
  x: multiplyWithKInferX<K>,
): multiplyWithKReturn<K> => (k * x) as multiplyWithKReturn<K>;

/**
 * A function to get the converted typed after dividing with proportionality constant
 *
 * @param k - ProportionalityConstant<Y,X> -> Y ∝ X -> X = Y/k
 * @param y - Value of type Y
 * @returns x - Value of type X
 */
export const divideWithK = <K extends ProportionalityConstant<any, any>>(
  k: K,
  y: divideWithKInferY<K>,
): divideWithKReturn<K> => (y / k) as divideWithKReturn<K>;


================================================
FILE: src/standardLib.ts
================================================
import { Nominal } from './index';

/***
 * This is a replacement for Object.keys which actually types the keys correctly
 *
 * In javascript Object.keys makes the keys strings, so this can only be used with the record is using string keys
 */
export const keys = <T extends string>(obj: Record<T, any>): T[] =>
  Object.keys(obj) as T[];

/**
 * Add values of the same type, a way to add values of some nominal of number can get the sum of the values typed correctly
 */
export const plus = <T extends number>(...arg: T[]): T => {
  const sum = arg.reduce((acc, cur) => acc + cur, 0);
  return sum as T;
};

/**
 * Subtract values of the same type, a way to subtract values of some nominal of number can get the difference of the values typed correctly
 */
export const minus = <T extends number>(a: T, b: T): T => {
  return (a - b) as T;
};

/**
 * Decorate number as negative value
 */
export type Negative<T extends number> = Nominal<'Negative', T>;
/**
 * Create a number decorated as negative, will throw an error if the number is not negative
 */
export const Negative = <T extends number>(value: T): Negative<T> => {
  if (value > 0) {
    throw new Error('Value must be negative');
  }
  return value as Negative<T>;
};

/**
 * Decorate number as zero
 */
export type Zero<T extends number> = Nominal<'Zero', T>;

/**
 * Decorate number as negative or zero
 */
export type NegativeOrZero<T extends number> = Negative<T> | Zero<T>;
/**
 * Decorate number as negative or zero
 *
 * Will throw an error if the number is positive
 */
export const NegativeOrZero = <T extends number>(
  value: T,
): NegativeOrZero<T> => {
  if (value > 0) {
    throw new Error('Value must be negative or zero');
  }
  return value as NegativeOrZero<T>;
};


================================================
FILE: tsconfig.json
================================================
{
	"compilerOptions": {
		/* Visit https://aka.ms/tsconfig.json to read more about this file */
		/* Basic Options */
		// "incremental": true,                         /* Enable incremental compilation */
		"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
		"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
		// "lib": [],                                   /* Specify library files to be included in the compilation. */
		// "allowJs": true,                             /* Allow javascript files to be compiled. */
		// "checkJs": true,                             /* Report errors in .js files. */
		// "jsx": "preserve",                           /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
		// "declaration": true,                         /* Generates corresponding '.d.ts' file. */
		// "declarationMap": true,                      /* Generates a sourcemap for each corresponding '.d.ts' file. */
		// "sourceMap": true,                           /* Generates corresponding '.map' file. */
		// "outFile": "./",                             /* Concatenate and emit output to single file. */
		// "outDir": "./",                              /* Redirect output structure to the directory. */
		// "rootDir": "./",                             /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
		// "composite": true,                           /* Enable project compilation */
		// "tsBuildInfoFile": "./",                     /* Specify file to store incremental compilation information */
		// "removeComments": true,                      /* Do not emit comments to output. */
		"noEmit": true,                              /* Do not emit outputs. */
		// "importHelpers": true,                       /* Import emit helpers from 'tslib'. */
		// "downlevelIteration": true,                  /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
		// "isolatedModules": true,                     /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
		/* Strict Type-Checking Options */
		"strict": true, /* Enable all strict type-checking options. */
		// "noImplicitAny": true,                       /* Raise error on expressions and declarations with an implied 'any' type. */
		// "strictNullChecks": true,                    /* Enable strict null checks. */
		// "strictFunctionTypes": true,                 /* Enable strict checking of function types. */
		// "strictBindCallApply": true,                 /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
		// "strictPropertyInitialization": true,        /* Enable strict checking of property initialization in classes. */
		// "noImplicitThis": true,                      /* Raise error on 'this' expressions with an implied 'any' type. */
		// "alwaysStrict": true,                        /* Parse in strict mode and emit "use strict" for each source file. */
		/* Additional Checks */
		// "noUnusedLocals": true,                      /* Report errors on unused locals. */
		// "noUnusedParameters": true,                  /* Report errors on unused parameters. */
		// "noImplicitReturns": true,                   /* Report error when not all code paths in function return a value. */
		// "noFallthroughCasesInSwitch": true,          /* Report errors for fallthrough cases in switch statement. */
		// "noUncheckedIndexedAccess": true,            /* Include 'undefined' in index signature results */
		// "noImplicitOverride": true,                  /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
		// "noPropertyAccessFromIndexSignature": true,  /* Require undeclared properties from index signatures to use element accesses. */
		/* Module Resolution Options */
		"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
		// "baseUrl": "./",                             /* Base directory to resolve non-absolute module names. */
		// "paths": {},                                 /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
		// "rootDirs": [],                              /* List of root folders whose combined content represents the structure of the project at runtime. */
		"typeRoots": [
			"./node_modules/@types",
		], /* List of folders to include type definitions from. */
		// "types": [],                                 /* Type declaration files to be included in compilation. */
		// "allowSyntheticDefaultImports": true,        /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
		"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
		// "preserveSymlinks": true,                    /* Do not resolve the real path of symlinks. */
		// "allowUmdGlobalAccess": true,                /* Allow accessing UMD globals from modules. */
		/* Experimental Options */
		// "experimentalDecorators": true,              /* Enables experimental support for ES7 decorators. */
		// "emitDecoratorMetadata": true,               /* Enables experimental support for emitting type metadata for decorators. */
		/* Advanced Options */
		"skipLibCheck": true, /* Skip type checking of declaration files. */
		"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
    "noUncheckedIndexedAccess": true
	},
	"exclude": [
		"node_modules",
		".build"
	]
}
Download .txt
gitextract_m2ssrx3h/

├── .gitignore
├── .vscode/
│   └── settings.json
├── Readme.md
├── examples/
│   ├── basic.ts
│   ├── composing.ts
│   ├── proportionalityConstant.ts
│   ├── safeRecord.ts
│   └── sort.ts
├── package.json
├── rome.json
├── src/
│   ├── index.ts
│   ├── proportionalityConstant.ts
│   └── standardLib.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (23 symbols across 8 files)

FILE: examples/basic.ts
  type Minutes (line 5) | type Minutes = Nominal<'Minutes', number>;
  type Seconds (line 6) | type Seconds = Nominal<'Seconds', number>;

FILE: examples/composing.ts
  type SortedArray (line 3) | type SortedArray<T> = Nominal<'sortedArray', T[]>;
  type NonEmptyArray (line 14) | type NonEmptyArray<K, T extends K[]> = Nominal<'nonEmptyArray', T>;
  type NonEmptySorted (line 15) | type NonEmptySorted<T> = NonEmptyArray<T, SortedArray<T>>;

FILE: examples/proportionalityConstant.ts
  type Pixel (line 10) | type Pixel = Nominal<'Pixel', number>;
  type Seconds (line 11) | type Seconds = Nominal<'Seconds', number>;
  type PixelPerSecond (line 12) | type PixelPerSecond = ProportionalityConstant<Pixel, Seconds>;
  constant PIXEL_PER_SECOND (line 14) | const PIXEL_PER_SECOND: PixelPerSecond = 1 as PixelPerSecond;
  type A (line 20) | type A = typeof a;
  type C (line 26) | type C = typeof c;
  type _cases (line 28) | type _cases = [Expect<Equal<A, Pixel>>, Expect<Equal<C, Seconds>>];

FILE: examples/safeRecord.ts
  type SafeRecord (line 3) | type SafeRecord<V, R extends string = ''> = Nominal<

FILE: examples/sort.ts
  type SortedArray (line 3) | type SortedArray<T> = Nominal<'sortedArray', T[]>;

FILE: src/index.ts
  type Nominal (line 3) | type Nominal<Name extends string, Type> = Type & {

FILE: src/proportionalityConstant.ts
  type ProportionalityConstant (line 17) | type ProportionalityConstant<
  type multiplyWithKReturn (line 25) | type multiplyWithKReturn<K> = K extends ProportionalityConstant<
  type multiplyWithKInferX (line 32) | type multiplyWithKInferX<K> = K extends ProportionalityConstant<
  type divideWithKReturn (line 39) | type divideWithKReturn<K> = K extends ProportionalityConstant<infer _Y, ...
  type divideWithKInferY (line 43) | type divideWithKInferY<K> = K extends ProportionalityConstant<infer Y, i...

FILE: src/standardLib.ts
  type Negative (line 29) | type Negative<T extends number> = Nominal<'Negative', T>;
  type Zero (line 43) | type Zero<T extends number> = Nominal<'Zero', T>;
  type NegativeOrZero (line 48) | type NegativeOrZero<T extends number> = Negative<T> | Zero<T>;
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (19K chars).
[
  {
    "path": ".gitignore",
    "chars": 12,
    "preview": "node_modules"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 219,
    "preview": "{\n  \"[typescriptreact]\": {\n    \"editor.defaultFormatter\": \"rome.rome\"\n  },\n  \"[typescript]\": {\n    \"editor.defaultFormat"
  },
  {
    "path": "Readme.md",
    "chars": 3252,
    "preview": "# Nominal\nThe right way to do types in typescript.\n\n## Installation\n\n```bash\nnpm install nominal-types\n\nyarn install nom"
  },
  {
    "path": "examples/basic.ts",
    "chars": 604,
    "preview": "// After Nominal\nimport { Nominal } from '../src';\nimport { Equal, Expect } from '@type-challenges/utils';\n\ntype Minutes"
  },
  {
    "path": "examples/composing.ts",
    "chars": 833,
    "preview": "import { Nominal } from '../src';\n\ntype SortedArray<T> = Nominal<'sortedArray', T[]>;\n\nconst sort = <T>(arr: T[]): Sorte"
  },
  {
    "path": "examples/proportionalityConstant.ts",
    "chars": 769,
    "preview": "import { Equal, Expect } from '@type-challenges/utils';\n\nimport {\n  divideWithK,\n  multiplyWithK,\n  Nominal,\n  Proportio"
  },
  {
    "path": "examples/safeRecord.ts",
    "chars": 807,
    "preview": "import { Nominal } from '../src';\n\ntype SafeRecord<V, R extends string = ''> = Nominal<\n  'safeRecordSymbol',\n  Record<R"
  },
  {
    "path": "examples/sort.ts",
    "chars": 846,
    "preview": "import { Nominal } from '../src';\n\ntype SortedArray<T> = Nominal<'sortedArray', T[]>;\n\nconst sort = <T>(arr: T[]): Sorte"
  },
  {
    "path": "package.json",
    "chars": 427,
    "preview": "{\n  \"name\": \"nominal-types\",\n  \"version\": \"0.2.0\",\n  \"description\": \"Nominal types for better typesafety\",\n  \"main\": \"sr"
  },
  {
    "path": "rome.json",
    "chars": 237,
    "preview": "{\n  \"linter\": {\n    \"enabled\": true,\n    \"rules\": {\n      \"recommended\": true\n    }\n  },\n  \"formatter\": {\n    \"enabled\":"
  },
  {
    "path": "src/index.ts",
    "chars": 181,
    "preview": "const M = Symbol();\n\nexport type Nominal<Name extends string, Type> = Type & {\n  readonly [M]: [Name];\n};\n\nexport * from"
  },
  {
    "path": "src/proportionalityConstant.ts",
    "chars": 1894,
    "preview": "// export type xPERy<X, Y> =\n\n/**\n * ProportionalityConstant is a type that represents a constant that is used to conver"
  },
  {
    "path": "src/standardLib.ts",
    "chars": 1746,
    "preview": "import { Nominal } from './index';\n\n/***\n * This is a replacement for Object.keys which actually types the keys correctl"
  },
  {
    "path": "tsconfig.json",
    "chars": 5948,
    "preview": "{\n\t\"compilerOptions\": {\n\t\t/* Visit https://aka.ms/tsconfig.json to read more about this file */\n\t\t/* Basic Options */\n\t\t"
  }
]

About this extraction

This page contains the full source code of the modfy/nominal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (17.4 KB), approximately 4.9k tokens, and a symbol index with 23 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!