Skip to content

Commit

Permalink
feat(strongly-typed): initial commit
Browse files Browse the repository at this point in the history
Add an initial offering for , which will let consumers optionally apply strong typing to their .
  • Loading branch information
alecgibson committed Nov 15, 2024
1 parent 09998ae commit 0727255
Show file tree
Hide file tree
Showing 17 changed files with 692 additions and 0 deletions.
19 changes: 19 additions & 0 deletions packages/container/libraries/strongly-typed/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Typescript compiled files
/lib/**

/tsconfig.tsbuildinfo
/tsconfig.cjs.tsbuildinfo
/tsconfig.esm.tsbuildinfo

# Test coverage report
/coverage

# Test mutation report
/reports

# node modules
/node_modules/

# Turborepo files
.turbo/

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"*.js": [
"prettier --write"
],
"*.ts": [
"prettier --write",
"eslint"
]
}
17 changes: 17 additions & 0 deletions packages/container/libraries/strongly-typed/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
**/*.spec.js
**/*.spec.js.map
**/*.ts
!lib/**/*.d.ts
lib/**/*.spec.d.ts

.lintstagedrc.json
eslint.config.mjs
jest.config.mjs
jest.config.stryker.mjs
jest.js.config.mjs
prettier.config.mjs
stryker.config.mjs
tsconfig.json
tsconfig.cjs.json
tsconfig.esm.json
tsconfig.tsbuildinfo
1 change: 1 addition & 0 deletions packages/container/libraries/strongly-typed/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @inversifyjs/strongly-typed
110 changes: 110 additions & 0 deletions packages/container/libraries/strongly-typed/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
[![Test coverage](https://codecov.io/gh/inversify/monorepo/branch/main/graph/badge.svg?flag=%40inversifyjs%2Fstrongly-typed)](https://codecov.io/gh/inversify/monorepo/branch/main/graph/badge.svg?flag=%40inversifyjs%2Fstrongly-typed)
[![npm version](https://img.shields.io/github/package-json/v/inversify/monorepo?filename=packages%2Fcontainer%2Flibraries%2Fstrongly-typed%2Fpackage.json&style=plastic)](https://www.npmjs.com/package/@inversifyjs/strongly-typed)

# @inversifyjs/strongly-typed

Type definitions for adding strong typing to the `Container` and `@inject()` decorator.


## Getting started

This library can be used in a couple of ways, depending on your preference.

All usages wind up with you having a strongly-typed `TypedContainer`, which is a generic class that accepts a binding map as a type argument, which forms the contract that your container will adhere to:

```ts
import { TypedContainer } from '@inversifyjs/strongly-typed';

interface Foo { foo: string }
interface Bar { bar: string }

interface BindingMap {
foo: Foo;
bar: Bar;
}

const container = new TypedContainer<BindingMap>();

// Bindings are now strongly typed:

container.bind('foo').toConstantValue({foo: 'abc'}); // ok
container.rebind('foo').toConstantValue({unknown: 'uh-oh'}) // compilation error

let foo: Foo = container.get('foo') // ok
foo = container.get('bar') // compilation error
foo = container.get('unknown-identifier') // compilation error
```

### Instantiation

The simplest way to use the library is to directly construct a `TypedContainer`:

```ts
import { TypedContainer } from '@inversifyjs/strongly-typed';

const container = new TypedContainer<BindingMap>();
```

This class is actually just a re-typed re-export of the vanilla `Container`, so shares all underlying functionality.

### Type assertion

If you'd prefer to keep this library out of your final dependency tree, you can just import the types and perform a type assertion:

```ts
import { Container } from 'inversify';
// The type import will be stripped during transpilation
import type { TypedContainer } from '@inversifyjs/strongly-typed';

const container = new Container() as TypedContainer<BindingMap>;
```


## Advanced usage

### `Promise` bindings

`inversify` allows binding `Promise`s, but these **must** be retrieved using `getAsync()` trying to resolve them using `get()` will throw.

The type signatures will help to enforce this if you show an async binding in the binding map with a `Promise`:

```ts
interface BindingMap {
number: number;
asyncNumber: Promise<number>;
}

const container = new TypedContainer<BindingMap>();

container.get('number') // number
container.get('asyncNumber') // compiler error
container.getAsync('asyncNumber') // Promise<number>
```

### Container hierarchies

A strongly-typed child container can be created from a parent container.

This strong typing is optional for the child:

```ts
const parent = new TypedContainer<BindingMap>();
const child = parent.createChild(); // weakly typed
```

If the child is strongly-typed, its binding will automatically be adjusted to include the parent types:

```ts
const parent = new TypedContainer<{foo: Foo}>();
const child = parent.createChild<{bar: Bar}>();
child.get('bar') // ok
child.get('foo') // ok
```

A child may also override a parent's bindings with a completely unrelated type:

```ts
const parent = new TypedContainer<{foo: Foo}>();
const child = parent.createChild<{foo: Bar}>();
const resolved: Bar = child.get('foo');
```
3 changes: 3 additions & 0 deletions packages/container/libraries/strongly-typed/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import myconfig from '@inversifyjs/foundation-eslint-config';

export default [...myconfig];
3 changes: 3 additions & 0 deletions packages/container/libraries/strongly-typed/jest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { tsGlobalConfig } from '@inversifyjs/foundation-jest-config';

export default tsGlobalConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { jsGlobalConfig } from '@inversifyjs/foundation-jest-config';

export default jsGlobalConfig;
71 changes: 71 additions & 0 deletions packages/container/libraries/strongly-typed/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"author": "Alec Gibson",
"bugs": {
"url": "https://github.com/inversify/monorepo/issues"
},
"description": "InversifyJs strong type definitions",
"devDependencies": {
"@eslint/js": "9.13.0",
"@jest/globals": "29.7.0",
"@types/node": "20.17.4",
"@typescript-eslint/eslint-plugin": "8.12.2",
"@typescript-eslint/parser": "8.12.2",
"eslint": "9.13.0",
"jest": "29.7.0",
"prettier": "3.3.3",
"rimraf": "6.0.1",
"ts-jest": "29.2.5",
"typescript": "5.6.3"
},
"devEngines": {
"node": "^20.18.0",
"pnpm": "^9.12.1"
},
"homepage": "https://inversify.io",
"keywords": [
"dependency injection",
"dependency inversion",
"di",
"inversion of control container",
"ioc",
"javascript",
"node",
"typescript"
],
"license": "MIT",
"main": "lib/cjs/index.js",
"module": "lib/esm/index.js",
"exports": {
".": {
"import": "./lib/esm/index.js",
"require": "./lib/cjs/index.js"
}
},
"name": "@inversifyjs/strongly-typed",
"peerDependencies": {
"inversify": ">=6.0.3"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/inversify/monorepo.git"
},
"scripts": {
"build": "pnpm run build:cjs && pnpm run build:esm",
"build:cjs": "tsc --build tsconfig.cjs.json && pnpm exec foundation-ts-package-cjs ./lib/cjs",
"build:esm": "webpack && pnpm exec foundation-ts-package-esm ./lib/esm",
"build:clean": "rimraf lib",
"format": "prettier --write ./src/**/*.ts",
"lint": "eslint ./src",
"prebuild": "pnpm run build:clean",
"test": "jest --config=jest.config.mjs --runInBand",
"test:js": "jest --config=jest.js.config.mjs --runInBand",
"test:js:coverage": "pnpm run test:unit:js --coverage",
"test:uncommitted": "pnpm run test --changedSince=HEAD",
"test:unit:js": "pnpm run test:js --selectProjects Unit"
},
"sideEffects": false,
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import config from '@inversifyjs/foundation-prettier-config';

export default config;
Loading

0 comments on commit 0727255

Please sign in to comment.