Git Product home page Git Product logo

ts's Introduction

ts

Node CI codecov

Monorepo of typescript projects.

Packages

⚠️⚠️ NOTE! I started this repo as a way to learn about monorepo tooling (specifically, rush). Some of the packages in it have become reasonably popular, and reasonably stable. So, I'm going to slowly move them out into their own repos, one by one. Once all are moved out this repo will be archived. ⚠️⚠️

Moved

  • expect-type - Compile-time tests for types. Useful to make sure types don't regress into being overly-permissive as changes go in over time.
  • eslint-plugin-codegen - An eslint plugin for inline codegen, with presets for barrels, jsdoc to markdown and a monorepo workspace table of contents generator. Auto-fixes out of sync code.
  • fs-syncer - A helper to recursively read and write text files to a specified directory.

Still here

  • io-ts-extra - Adds pattern matching, optional properties, and several other helpers and types, to io-ts.
  • memorable-moniker - Name generator with some in-built dictionaries and presets.

Development

Packages are managed using rush. Make sure rush is installed:

npm install --global @microsoft/rush

Then install, build, lint and test with:

rush update
rush build
rush lint
rush test

rush update should be run when updating the main branch too.


Add a dependency to a package (for example, adding lodash to fictional package in this monorepo some-pkg):

cd packages/some-pkg
rush add --package lodash
rush add --package @types/lodash --dev

You can also manually edit package.json then run rush update.

Create a new package:

cd packages
mkdir new-pkg
cd new-pkg
node ../../tools/rig/init # sets up package.json, .eslintrc.js, tsconfig.json, jest.config.js

Then open rush.json, find the projects array, and adda new entry: { "packageName": "new-pkg", "projectFolder": "packages/new-pkg" }

Publishing

publish

Publishing is automated, but kicked off manually. The process is:

  • Changes to published packages in this repo should be proposed in a pull request
  • On every pull request, a GitHub action uses the rush change command to create a changefile:
    • the change is based on the PR title and body:
      • if the words "BREAKING CHANGE" appear anywhere, it's considered "major"
      • if the PR title starts with "chore", or "fix", it's considered a "patch"
      • otherwise, it's considered "minor"
    • the created changefile is pushed to the PR's branch, and a comment is left on the PR (example PR, comment and change)
    • if the PR title or body is edited, or changes are pushed, the job will re-run and push a modification if necessary
    • most of the time, no change is necessary and the job exits after no-oping
    • if necessary, rush change can also be run locally to add additional messages - but ideally the PR title would be descriptive enough
    • the changefile should be merged in along with the rest of the changes

When a PR is merged, publishing is initiated by kicking off the publish worfklow:

  • Clicking "Run workflow" will start another GitHub action:
    • The workflow runs rush publish, which uses the changefiles merged with feature PRs, bumps versions and create git tags
    • When the publish step succeeds, a custom script reads the generated CHANGELOG.json files to create a GitHub release
Old instructions

Links to trees with previous iteration of publish instructions:

ts's People

Contributors

dependabot[bot] avatar jpdenford avatar mmkal avatar olance avatar papb avatar renovate[bot] avatar rraziel avatar yenbekbay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ts's Issues

Optional non nullable

I have noticed that the t.optional is equivalent to T|undefined|null which may be a quite different behaviour from T|undefined and T, in particular with the new typescript 4.4 --exactOptionalPropertyTypes

Would be possible to add to more optionals to the library? In the specific:

optionalNonNull for undefined properties, compliant with typescript without --exactOptionalPropertyTypes

// Type definition
export declare const optionalNonNull: <RT extends t.Mixed>(rt: RT, name?: string | undefined) => t.UnionC<[RT, t.UndefinedC]> & Optional;

// Implementation
export const optionalNonNull = <RT extends t.Mixed>(rt: RT, name?: string) => {
    const unionType = union([rt, undefinedType], name || rt.name + '?');
    return Object.assign(unionType, { optional: true } as Optional);
};

optionalExact for exact properties, compliant with typescript with --exactOptionalPropertyTypes

// Type definition
export declare const optionalExact: <RT extends t.Mixed>(rt: RT) => RT & Optional;

// Implementation
export const optionalExact = <RT extends t.Mixed>(rt: RT) => {
    return Object.assign(rt, { optional: true } as Optional);
};

Async custom codegen functions?

First off -- I love the eslint-plugin-codegen tool! The idea of having code generation handled by the linter is really smart.

Is there any chance that you could allow custom codegen functions to be async? Let me know if there's anything I can help with!

fs-syncer remove()

Hey. Just a thought for fs-syncer - could it add removeWrite/removeSync methods to clear down files/dir and be useful for jest.afterAll() or similar?

[expect-type] No errors when fields differ by the readonly modifier.

First off, thanks for the expect-type module, it's working pretty well for us.

But we've hit an issue. I expected the following to not compile but it does not show any errors.

expectTypeOf<{ readonly a: string }>().toEqualTypeOf<{ a: string }>();
expectTypeOf<{ a: string }>().toEqualTypeOf<{ readonly a: string }>();

I understand that the readonly fields don't affect assignability, but is it not possible for toEqualTypeOf to detect the difference?

`.toEqualTypeOf` sometimes removes `undefined`

expectTypeOf('' as string | null | undefined).toEqualTypeOf<string | null | undefined>() doesn't work, it expects string | null instead of string | null | undefined

The same happens with expectTypeOf(null as null | undefined).toEqualTypeOf<null | undefined>()

But weirdly, it works with expectTypeOf(undefined).toEqualTypeOf<undefined>()

My tsconfig

{
  "compilerOptions": {
    "alwaysStrict": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noEmitOnError": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "strictFunctionTypes": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "ES5",
    "lib": ["ES2020"],
    "baseUrl": ".",
    "rootDir": "src",
    "outDir": "dist-tsc",
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "src/**/*.spec.ts", "src/e2e/**/*"]
}

[io-ts-extra] remove ToA extends ToO constraint for mapper/parser

Hi! 👋

Following on from my other issue, I used this diff on mapper.d.ts to fix the typings for parser and mapper. This will break the mapper function, though... See my other issue for my suggested concrete implementation on the mapper function.

Today I used patch-package to patch [email protected] for the project I'm working on.

Here is the diff that solved my problem:

diff --git a/node_modules/io-ts-extra/dist/mapper.d.ts b/node_modules/io-ts-extra/dist/mapper.d.ts
index 8765a8f..3426662 100644
--- a/node_modules/io-ts-extra/dist/mapper.d.ts
+++ b/node_modules/io-ts-extra/dist/mapper.d.ts
@@ -1,15 +1,31 @@
 import * as t from 'io-ts';
 export declare type Decoder<A, O = A, I = unknown> = Omit<t.Type<A, O, I>, 'encode'>;
 interface Mapper {
-    <From, ToO, ToA extends ToO | t.Branded<ToO, any>>(from: t.Type<From>, to: t.Type<ToA, ToO>, map: (f: From) => ToO): Decoder<ToA, From> & {
-        from: From;
-        to: ToA;
-    };
-    <From, ToO, ToA extends ToO | t.Branded<ToO, any>>(from: t.Type<From>, to: t.Type<ToA, ToO>, map: (f: From) => ToO, unmap: (t: ToA) => From): t.Type<ToA, From> & {
-        from: From;
-        to: ToA;
-    };
-}
+    <
+      TFrom extends t.Any,
+      TTo extends t.Any,
+      From = t.TypeOf<TFrom>,
+      ToA = t.TypeOf<TTo>,
+      ToO = t.OutputOf<TTo>
+    >(
+      from: TFrom,
+      to: TTo,
+      map: (f: From) => ToO,
+      unmap: (t: ToA) => From
+    ): t.Type<ToA, From> & {from: From; to: ToA};
+
+    <
+      TFrom extends t.Any,
+      TTo extends t.Any,
+      From = t.TypeOf<TFrom>,
+      ToA = t.TypeOf<TTo>,
+      ToO = t.OutputOf<TTo>
+    >(
+      from: TFrom,
+      to: TTo,
+      map: (f: From) => ToO
+    ): Decoder<ToA, From> & {from: From; to: ToA};
+  }
 /**
  * A helper for building "parser-decoder" types - that is, types that validate an input,
  * transform it into another type, and then validate the target type.
@@ -46,7 +62,11 @@ export declare const mapper: Mapper;
  * @param decode transform a string into the target type
  * @param encode transform the target type back into a string
  */
-export declare const parser: <ToO, ToA extends ToO | t.Branded<ToO, any>>(type: t.Type<ToA, ToO, unknown>, decode: (value: string) => ToO, encode?: (value: ToA) => string) => t.Type<ToA, string, unknown> & {
+export declare const parser: <
+TTo extends t.Any,
+ToA = t.TypeOf<TTo>,
+ToO = t.OutputOf<TTo>
+>(type: TTo, decode: (value: string) => ToO, encode?: (value: ToA) => string) => t.Type<ToA, string, unknown> & {
     from: string;
     to: ToA;
 };

This issue body was partially generated by patch-package.

[expect-type] Clarification on `toEqualType` versus `toMatchType`

Hello!

Thanks for the explanation in this comment. However, it is still not fully clear to me (probably because I'm not familiar with Jest's toMatchObject either).

Please confirm if my understanding is correct:

let a: A;
let b: B;

// Passes if and only if `A` is identical to `B`
expectTypeOf(a).toEqualTypeOf(b)

// Passes if and only if `A extends B`
// In other words, passes if and only if the assignment `b = a` is valid
expectTypeOf(a).toMatchTypeOf(b)

Is this correct?

Thanks!!

Using pure javascript instead of node dependencies

I'm developing a product on Cloudflare Workers and I wanted to use io-ts-extra for handling optional types. Unfortunately, workers platform does not support Node, so It's not possible to use the library in workers environments. I wonder if it's possible to shift node dependencies to javascript API for the library's more useability?

False positives for type equality

Unfortunately, while #33 now catches deep anys, it seems to have weakened other equality checks. In 0.7.3, this assertion would (correctly) fail:

type NoParam = () => void;
type HasParam = (s: string) => void;

expectTypeOf<NoParam>().toEqualTypeOf<HasParam>();

But starting with 0.7.4, which contains that fix, this assertion passes.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update actions/cache action to v4
  • chore(deps): update actions/checkout action to v4
  • chore(deps): update actions/github-script action to v7
  • chore(deps): update actions/labeler action to v5
  • chore(deps): update actions/setup-node action to v4
  • chore(deps): update codecov/codecov-action action to v4
  • 🔐 Create all rate-limited PRs at once 🔐

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

  • chore(deps): update devdependencies (@babel/types, @microsoft/rush-lib, @types/babel__generator, @types/babel__traverse, @types/dedent, @types/eslint, @types/glob, @types/jest, @types/js-yaml, @types/lodash, @types/minimatch, @types/node, @types/seedrandom, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, check-clean, eslint, eslint-config-xo, eslint-config-xo-typescript, eslint-plugin-codegen, eslint-plugin-import, eslint-plugin-jest, eslint-plugin-prettier, eson-parser, expect-type2, minimatch, prettier, sort-package-json, ts-jest, ts-loader, typescript, webpack)
  • fix(deps): update eslint-plugin-codegen (@babel/generator, read-pkg-up)
  • fix(deps): update devdependencies (major) (@actions/github, @types/eslint, @types/glob, @types/jest, @types/js-yaml, @types/minimatch, @types/node, @types/seedrandom, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, concurrently, dedent, eslint, eslint-config-xo-typescript, eslint-plugin-jest, eslint-plugin-prettier, eslint-plugin-unicorn, find-up, jest, js-yaml, minimatch, prettier, rimraf, sort-package-json, ts-jest, ts-loader, ts-node, typescript, webpack, webpack-cli)
  • fix(deps): update eslint-plugin-codegen (major) (expect, glob, js-yaml, read-pkg-up)

Detected dependencies

github-actions
.github/workflows/build.yml
  • actions/checkout v2
  • actions/setup-node v2
  • actions/cache v2
  • actions/cache v2
  • codecov/codecov-action v1
.github/workflows/changes.yml
  • actions/checkout v2
  • actions/setup-node v2
  • actions/github-script v3
.github/workflows/labeler.yml
  • actions/labeler v3
.github/workflows/post-release.yml
  • apexskier/github-release-commenter v1
.github/workflows/post-renovate.yml
  • actions/checkout v2
  • actions/setup-node v2
.github/workflows/publish.yml
  • actions/checkout v2
  • actions/setup-node v2
  • actions/github-script v3
npm
package.json
packages/check-clean/package.json
packages/eslint-plugin-codegen/package.json
  • @babel/core ^7.11.6
  • @babel/generator ~7.12.0
  • @babel/parser ^7.11.5
  • @babel/traverse ^7.11.5
  • expect ^26.0.0
  • fp-ts ^2.1.0
  • glob ^7.1.4
  • io-ts ^2.2.4
  • js-yaml ^3.14.0
  • lodash ^4.17.15
  • string.prototype.matchall ^4.0.2
  • read-pkg-up ^7.0.1
  • @babel/types 7.12.11
  • @types/babel__generator 7.6.2
  • @types/babel__traverse 7.11.0
  • @types/dedent 0.7.0
  • @types/eslint 7.2.6
  • @types/glob 7.1.3
  • @types/js-yaml 3.12.5
  • @types/lodash 4.14.165
  • @types/minimatch 3.0.3
  • dedent 0.7.0
  • expect-type2 0.14.0
  • minimatch 3.0.4
  • eslint 7.15.0
  • ts-node 9.1.1
packages/io-ts-extra/package.json
  • fp-ts ^2.1.0
  • io-ts ^2.2.4
  • @types/js-yaml 3.12.5
  • @types/lodash 4.14.165
  • expect-type2 0.14.0
  • js-yaml ^3.14.0
  • lodash ^4.17.15
packages/memorable-moniker/package.json
  • seedrandom ^3.0.5
  • @types/lodash 4.14.165
  • @types/seedrandom 2.4.28
  • expect-type2 0.14.0
  • lodash ^4.17.15
tools/rig/package.json
  • @actions/github 4.0.0
  • @types/jest 26.0.19
  • @types/js-yaml 3.12.5
  • @types/node 14.14.14
  • @typescript-eslint/eslint-plugin 4.10.0
  • @typescript-eslint/parser 4.10.0
  • check-clean 0.3.0
  • concurrently 5.3.0
  • eslint 7.15.0
  • eslint-config-xo 0.33.1
  • eslint-config-xo-typescript 0.37.0
  • eslint-plugin-codegen 0.14.4
  • eslint-plugin-import 2.22.1
  • eslint-plugin-jest 24.1.3
  • eslint-plugin-prettier 3.3.0
  • eslint-plugin-unicorn 21.0.0
  • eson-parser 0.0.5
  • find-up 5.0.0
  • jest 26.6.3
  • js-yaml ^3.14.0
  • lodash ^4.17.15
  • prettier 2.2.1
  • rimraf 3.0.2
  • sort-package-json 1.48.0
  • ts-jest 26.4.4
  • ts-loader 8.0.12
  • typescript 4.1.3
  • webpack 4.44.2
  • webpack-cli 3.3.12
  • @microsoft/rush-lib 5.35.2
  • @types/eslint 7.2.6
  • @types/lodash 4.14.165

  • Check this box to trigger a request for Renovate to run again on this repository

Errors after upgrading to io-ts 2.2.17

After upgrading io-ts to 2.2.17, a definition as simple as:

t.type({
  adults: optional(t.union([t.number, t.null])),
})
or
sparseType({
  adults: optional(t.union([t.number, t.null])),
})

Shows the following error:

Argument of type 'UnionC<[NumberC, NullC]>' is not assignable to parameter of type 'Mixed'.
  Types of property 'pipe' are incompatible.
    Type '<B, IB, A extends IB, OB extends A>(this: Type<A, number | null, unknown>, ab: Type<B, OB, IB>, name?: string | undefined) => Type<B, number | null, unknown>' is not assignable to type '<B, IB, A extends IB, OB extends A>(this: Type<A, any, unknown>, ab: Type<B, OB, IB>, name?: string | undefined) => Type<B, any, unknown>'.
      The 'this' types of each signature are incompatible.
        Type 'Type<A, any, unknown>' is not assignable to type 'Type<IB, number | null, unknown>'.
          Types of property 'is' are incompatible.
            Type 'Is<A>' is not assignable to type 'Is<IB>'.
              Type predicate 'u is A' is not assignable to 'u is IB'.
                Type 'A' is not assignable to type 'IB'.
                  'IB' could be instantiated with an arbitrary type which could be unrelated to 'A'

Downgrading to io-ts 2.2.16 removes the error

Reporting a vulnerability

Hello!

I hope you are doing well!

We are a security research team. Our tool automatically detected a vulnerability in this repository. We want to disclose it responsibly. GitHub has a feature called Private vulnerability reporting, which enables security research to privately disclose a vulnerability. Unfortunately, it is not enabled for this repository.

Can you enable it, so that we can report it?

Thanks in advance!

PS: you can read about how to enable private vulnerability reporting here: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/configuring-private-vulnerability-reporting-for-a-repository

[io-ts-extra] Question about Mapper interface's generic args

Hi,

I'm happily using io-ts-extra to aid in my type-iness so thanks for taking the time to publish your library!

One of the things I really like is the mapper/parser interface that you've set up. I'm trying to nest parser codecs inside more complex types, and found a problem when trying to create a parser of a type that contains a parser type nested within it.

A contrived example:

// Given a codec for an array of numbers.
const arr = t.array(t.number);

// Define a parser for it.
const arr_string = t.parser(arr, s => s as any, s => s as any);
// E.g.
arr_string.decode('1,2');

// Define an object with an array of numbers as property,
// but will decode/encode that property as a string.
const obj = t.type({
  myArr: arr_string
})
// E.g.
obj.decode({ myArr: '1,2' })

// Define a parser forit
const obj_string = t.parser(obj, s => s as any, s => s as any);
obj_string.decode('{ "myArr": "1,2" }');

In the above, the codecs function correctly, however Typescript will complain about obj in const obj_string = t.parser(obj, ...); with (abbreviated)

Types of property 'is' are incompatible.

After some digging, I noticed that the Mapper interface expects the codec's actual type ToA to inherit from it output type ToO.

The reason the Mapper complains about using the parser as From is because the parser's ToO is now string, which obviously doesn't extend number[].

My question to you is why does the Mapper interface constrain ToA extends ToO? The original t.Type<A, O, I> has no such constraint.

Would it be safe to remove this constraint, since it prevents the harmonious nesting of mapper/parser types?

Is `toEqualTypeOf` as strong as this `IsExact` implementation from conditional-type-checks?

I found this implementation of IsExact in a package called conditional-type-checks.

I liked how it works, it seems to make more checks than your implementation of Equal:

export type Equal<Left, Right> = And<
[
Extends<Left, Right>, // prettier-break
Extends<Right, Left>,
Extends<keyof Left, keyof Right>,
Extends<keyof Right, keyof Left>
]
>

Question: are these implementations equivalent? Or is one of these implementations stricter than the other?

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.