GithubHelp home page GithubHelp logo

total-typescript / ts-reset Goto Github PK

View Code? Open in Web Editor NEW
7.6K 20.0 118.0 292 KB

A 'CSS reset' for TypeScript, improving types for common JavaScript API's

Home Page: https://www.totaltypescript.com/ts-reset

License: MIT License

TypeScript 100.00%
reset typescript

ts-reset's Introduction

TS Reset - Improved TypeScript's Built-in Typings

Without ts-reset:

  • ๐Ÿšจ .json (in fetch) and JSON.parse both return any
  • ๐Ÿคฆ .filter(Boolean) doesn't behave how you expect
  • ๐Ÿ˜ก array.includes often breaks on readonly arrays

ts-reset smooths over these hard edges, just like a CSS reset does in the browser.

With ts-reset:

  • ๐Ÿ‘ .json (in fetch) and JSON.parse both return unknown
  • โœ… .filter(Boolean) behaves EXACTLY how you expect
  • ๐Ÿฅน array.includes is widened to be more ergonomic
  • ๐Ÿš€ And several more changes!

Official Docs

Check out our docs page on Total TypeScript

ts-reset's People

Contributors

donavon avatar github-actions[bot] avatar kadrei avatar mattpocock avatar mefechoel 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ts-reset's Issues

[Feature request] Smarter `Object.entries`

This is an amazing project! Thanks a ton for the already great TypeScript resets! ๐ŸŽ‰

If possible, I'd love to have a better Object.entries array method that will treat the keys as a const instead of a primitive string/number. This can be useful in the following scenario:

const myVariable = {
  "bar": 1,
  "baz": "foo",
} as const;

// In this example, `key` is typed as `string`.
const a = Object.entries(myVariable).reduce((accumulator, [key, value]) => ({
  ...accumulator,
  [key]: `Value: ${value}`,
}), {});

In the example above, key is a string, but I'd argue that a "bar" | "baz" inferred type would be a better match in this case. I've managed to find a objectEntries helper method that suits my use case and can be used in the following example:

const myVariable = {
  "bar": 1,
  "baz": "foo",
} as const;

type Input<T extends object> = {
  [Key in keyof T]: T[Key];
};

const objectEntries = <T extends object>(
  input: T,
): [key: keyof T, value: T[keyof T]][] =>
  Object.entries<T[keyof T]>(input as Input<T>) as [
    key: keyof T,
    value: T[keyof T],
  ][];

// In this example, `key` is typed as `"bar" | "baz"`
const b = objectEntries(myVariable).reduce((accumulator, [key, value]) => ({
  ...accumulator,
  [key]: `Value: ${value}`,
}), {});

I'm looking forward to your reply and if this is a suitable addition to the project.


More info:

Improve type narrowing for `.includes`

Given the following code:

(["a", "b", "c"] as const).includes(SOME_VALUE as 'a' | 'b' | 'd' )

we get a Typeguard that SOME_VALUE is 'a' | 'b' | 'c' โ€” but in this case we know more about: we know it is not 'c' so it would be great to not have 'c' show up in the result again. The typeguard should narrow to 'a' | 'b'

One naive way to implement it would be something like:

interface ReadonlyArray<T> {
  includes<TSearch extends T | (TSReset.WidenLiteral<T> & {})>(
    searchElement: TSearch,
    fromIndex?: number,
  ): searchElement is T & TSearch;
}

Diff:

interface ReadonlyArray<T> {
-  includes(
-    searchElement: T | (TSReset.WidenLiteral<T> & {}),
+  includes<TSearch extends T | (TSReset.WidenLiteral<T> & {})>(
+    searchElement: TSearch,
    fromIndex?: number,
-  ): searchElement is T;
+  ): searchElement is T & TSearch;
}

Is there any reason this shouldn't be done? If not I'd be glad to open a PR.

Use tsconfig.json instead of import

Since it's global like lib.dom.d.ts, it makes more sense in the compiler options imho.

{
  "compilerOptions": {},
  "include": ["@total-typescript/ts-reset"]
}

It also avoids having to choose in what TS file to put your import "@total-typescript/ts-reset";

Array.isArray problem with narrowed type

Hi, I recently saw your YT video and wanted to add ts-reset to our project. But there is an issue which I find difficult to overcome:

Basically the problem is that isArray is always adding the type unknown[] to my variable, which I know is of type T | T[].
So when I check whether it's an array, I should know it's T[], but TS now thinks it's T[] & unknown[] which is a problem.

I tried to replicate it here:
https://www.typescriptlang.org/play?ts=4.9.5#code/JYOwLgpgTgZghgYwgAgIJSnAngYQPYgDOYUArgmHlMgN4BQyywh6mWAFHFAOYBcycEFgCU-LtyaFkpEAGsQeAO4gA2gF0A3HQC+dOmCwAHFAFUQXNgB4AKgD5kAXmTXkEAB6QQAEymtsl0BhoZBN7AH4Q5H5rLToYGQpgAmRIYhtbdgA3OAAbUgho4Vo6AEhShAJiJhAQYKdLAA1XDwhvKTMLfzsMzP4G9SKHe3oSkoB6MeRS3TKS4Bhkdj8sADpmZazc-OEikbma6E28iGEtEt1tIA

Any advice maybe? :)

Bug: library can't be installed as a dev dependency

Is there any way to make this lib not need to be a runtime dependency? Since it's only affecting typescript, shouldn't it be ok as a dev dependency?

pnpm prune --prod

node:internal/modules/cjs/loader:1078
  throw err;
  ^

Error: Cannot find module '@total-typescript/ts-reset'

Use `JsonValue` as `JSON.parse` Return Type?

Perhaps this would go further that what is wanted from this library, but I think it'd be nice if JSON.parse could return a type similar to (or the same as) JsonValue from type-fest (see https://github.com/sindresorhus/type-fest#json).

I've never used the optional reviver function in JSON.parse, but it looks like it can modify the return type beyond JsonValue, so perhaps it'd make sense to have a return type of JsonValue if no reviver is passed, then unknown if a reviver is passed?

Accept Generic Parameters for FormData, Response and Request

Hey @mattpocock ๐Ÿ‘‹ Hope you're well!

Looks like a cool project! ๐Ÿ‘€

Wonder if you'd be open for enabling some DX improvements such as enabling FormData, Response and Request to take generic type parameters.

These have been requested in TypeScript itself, but it seems like the requests won't be implemented:

Motivating Examples

FormData

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

type Options<Method> = {
  method?: Method;
}

export async function fetchApi<Path extends string, Method extends HttpMethod>(
  path: Path,
  options: Options<Method> & {
    formData: `${Method} ${Path}` extends `POST /exercise-checks`
      ? { id: string, file: File } // ๐Ÿ‘ˆ Could be FormData<{ id: string, file: File }>
      : `${Method} ${Path}` extends `PUT /exercise-checks/${number}`
      ? { file: File } // ๐Ÿ‘ˆ Could be FormData<{ file: File }>
      : never
  }): Promise<
    `${Method} ${Path}` extends `POST /exercise-checks`
      ? { id: string } | { errors: string[] }
      : `${Method} ${Path}` extends `PUT /exercise-checks/${number}`
      ? { id: string } | { errors: string[] }
      : never
  > {
  return '' as any;
}

const file = new File([''], '');
const goodFormData = { id: '1', file: file }; // ๐Ÿ‘ˆ Could be new FormData() + .append
const badFormData = { incorrectProperty: false }; // ๐Ÿ‘ˆ Could be new FormData() + .append

// โœ… No errors
await fetchApi('/exercise-checks', { method: 'POST', formData: goodFormData })
// โœ… No errors
await fetchApi('/exercise-checks/1', { method: 'PUT', formData: { file: file } })
// โœ… Errors, incorrect method
await fetchApi('/exercise-checks/1', { method: 'PUTzzzzz', formData: { file: file } })
// โœ… Error, incorrect path
await fetchApi('/xxxxx', { method: 'PUT', formData: { file: file } })
// โœ… Error, incorrect form data
await fetchApi('/exercise-checks/1', { method: 'POST', formData: badFormData })

TypeScript Playground

Response and Request

Before:

export async function POST(request: Request): Response {
  const body = await request.json();
     // ^? const body: any โŒ
  return new Response(JSON.stringify({
    abc: 123, // โŒ POST function return type cannot check type of response body object
  }))
}

After:

type RequestBody = { zzz: number };
type ResponseBody = { abc: number };

export async function POST(request: Request<RequestBody>): Response<ResponseBody> {
  const body = await request.json();
     // ^? const body: { zzz: number } โœ…
  return new Response(JSON.stringify({
    abc: 123, // โœ… type checked
  }))
}

Caveats

  1. Arguably, the Request body is unknown until runtime, so this is better handled instead with Zod or some other runtime validation. But for quick/simple projects without this validation, it's nice to be able to type the request body type.

[Bug] Breaks Fragment Typings

when using this library, "Fragment" imported from React only expects a single child which defeats the purpose of using a fragment:

import {Fragment} from 'react';

function F() {
  return (
    // type error
    <Fragment>
      <div/>
      <div/>
    </Fragment>
  )
}

Screenshot 2023-02-24 at 1 50 08 PM

removing the import from @total-typescript/ts-reset fixed my issue

make `isArray` more specific

I have a code:

  const path: string | string[];
  ...
  const paths = Array.isArray(path) ? path : [path];

With the new isArray assuming unknown[], this breaks the type of paths.

Could we make the isArray more smart that it can infer the generic type?

Bad example for .filter(Boolean)?

Is this a โ€œbadโ€ example since itโ€™ll also remove 0?

const filteredArray = [1, 2, undefined].filter(Boolean); // number[]

Would be cool with an example where .filter(Boolean) nicely removes undefined from the type but still is โ€œsafeโ€ (= can be used for real).

ts-reset for DOM lib

Hey @mattpocock, thanks for ts-reset. I've been thinking about making something similar for DOM specs. Several APIs say they exist, but they do not work across all browsers.

My plan on how to solve this is to use something like Playwright, inspect all DOM APIs and check that they exist and write a JSON object out towards the end of the test runner and then make a diff and where the APIs don't work across browser make the API optional, and append some docs with notes around which browsers support what.

What do you think about this being a part of or an extension of ts-reset?

Is it possible to add this only on a single file?

Having these types imported only in a single file may be helpful for existing projects, so they may introduce it gradually in their codebase or only include this in the new ts files they create.

Object.fromEntries

Hey, I'm a fan of your YouTube videos and I'm excited to start using ts-reset in my projects.

One feature I would really appreciate would be better typing for the Object constructor method Object.fromEntries:

// currently:
Object.fromEntries([["a", 5], ["b", 6]] as const) // { [k: string]: "a" | "b" }
// ideally:
Object.fromEntries([["a", 5], ["b", 6]] as const) // { a: 5, b: 6 }

I found an implementation at this blog post:

export type ArrayElement<A> = A extends readonly (infer T)[] ? T : never;
type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
type Cast<X, Y> = X extends Y ? X : Y
type FromEntries<T> = T extends [infer Key, any][]
  ? { [K in Cast<Key, string>]: Extract<ArrayElement<T>, [K, any]>[1]}
  : { [key in string]: any }
export type FromEntriesWithReadOnly<T> = FromEntries<DeepWriteable<T>>
function fromEntries<T extends Iterable<readonly [PropertyKey, any]>>(entries: T): FromEntriesWithReadOnly<T> {
  return Object.fromEntries(entries) as any
}

Not my code

Here's a playground link for the implementation: TS Playground Link

I'd be glad to write up a PR if you think this is worth adding.

Feature request - Smarter `Boolean`

This is a great project ๐Ÿ˜

I add a suggestion to "patch" Boolean because I have been stumped by it at multiple occasions, e.g:

const fn = (arg: 'string' | null) => {
  const bar = Boolean(arg)
  if (bar) {
      return arg.toUpperCase()
          // ^? (parameter) arg: "string" | null
  }

  const baz = !!arg
  if (baz) {
      return arg.toUpperCase()
          // ^? (parameter) arg: "string"
  }

  return arg
}

And the TS Playground link.


In real code examples, I usually have a combination of variables (e.g: const hasData = Boolean(!isLoading && data && !hasError)) and I found Boolean to be quite "dumb" compared to the less elegant !!. I don't know if it's normal and I'm missing something of if it could be patch like Array#filter.

String methods properly infering types

Methods such as toLowerCase and toUpperCase do not properly infer union type that are invoked on.

Typescript Playground Link

There is solution for that, but due to those methods being very ground level it may break things in legacy code.
Thus official typescript is not so keen to change those types.

interface String {
  toLowerCase<T extends string>(this: T): Lowercase<T>;
  toUpperCase<T extends string>(this: T): Uppercase<T>;
}

Separate any-to-unknown and less-strict rules

I think it would be good to have 2 separate sets of rules

  • any-to-unknown
  • less-strict

I'm a bit confused about

  • import "@total-typescript/ts-reset/array-includes";
  • import "@total-typescript/ts-reset/set-has";

Why would you want something less strict? Maybe you could give some examples to show why you would want that. I've been having scenarios with Array.includes() where sometimes it's nice to have T | U and sometimes it's easier with string but less "true".

Having separate sets of rules, it's easier to pick unknown-to-any rules which make your code safer and not the other one (which makes your code less true but improves DX).

While checking type of something unknown, expect the correct type as input.

As an example, when we are doing type check on runtime with Array.isArray(args: any)
args is any, first of all it can be unknown which is nicer.

But why not expect an array in the first place? So:

isArray<T extends unknown[] | readonly unknown[]>(arg: T | unknown): arg is T

So when we use it, we get this results:

const arr = [1, 2] as const // readonly [1, 2]
const arr1 = [1, 2] // number[]
const foo: unknown = null // unknown

if (Array.isArray(arr))
  arr // readonly [1, 2]

if (Array.isArray(arr1))
  arr1 // number[]

if (Array.isArray(foo))
  foo // unknown[] | readonly unknown[]

So if we are checking something that is already a known array, we don't make it unknown[]
While we are also still accepting anything unknown.

Also with this, if we know something is not an array or unknown or any we get type error.
Why is that important?
So let's say we had some unknown value in a large function and we check if it's an array.
Then a while later we narrow the type of the value higher in the function, so now we know it's not an array.
For example we check if it's a string and if it's a string, then we don't need to check if a string is an array, because that will always return false.
But now we forget the Array.isArray() check at the bottom, because TS didn't give any type errors.

This should be same for every type check, not just Array.isArray()

Before making a PR and etc. I wanted to here opinions on this.
And if there is a good reason that this is not being done.

Add support for objects `.includes`

const arr = [{ a: 1 }] as const;

let member = { a: 1 }  // type is { a: number }
arr.includes(member)   // ERROR: Not assignable
arr.includes({ a: 1 }) // This is fine

This might be non-trivial, but given what the new typing for .includes tries to achieve, I was surprised this wasn't working. It is easy to understand why it doesn't, given how it is implemented, but it would be great if that could be supported. We would need to extend the WidenLiteral to the object values if that is possible โ€” probably something recursive.

Missing LICENSE file

Please add a LICENSE file to this repo to specify what usages are allowed. Thank you!

Feedback and suggestions

Thanks a lot for this. It makes a lot of sense while we wait for TS to "fix" those typings (and remove any from the language ๐Ÿคช)

May I suggest 2 enhancements?

Use tsconfig.json instead of import

Since it's global like lib.dom.d.ts, it makes more sense in the compiler options imho.

Separate any-to-unknown and less-strict rules

I'm a bit confused about

  • import "@total-typescript/ts-reset/array-includes";
  • import "@total-typescript/ts-reset/set-has";

Why would you want something less strict? Maybe you could give some examples to show why you would want that. I've been having scenarios with Array.includes() where sometimes it's nice to have T | U and sometimes it's easier with string but less "true".

Meanwhile, I would separate those sets of rules so your users could choose easily to pick unknown-to-any rules which make your code safer and not the other one.

Fix the unsound parts of Object.values/Object.entries

It's a great idea not to "fix" Object.keys as it is not broken, I fully support that! But you could push the reasoning further and actually fix the various broken parts of Object.values and Object.entries.

For instance it can introduce unexpected anys:

// Return type: any[] | null
const f = (x: unknown) => {
    if (x) {
        return Object.values(x);
    }
    return null;
}

// Return type: [string, any][] | null
const g = (x: unknown) => {
    if (x) {
        return Object.entries(x);
    }
    return null;
}

And it also does not respect structural typing and the possibility of having extra properties:

// Return type: number[], but x could have other properties with different types, should really be unknown[]
const h = (x: {a: number}) => Object.values(x);

// Return type: [string, number][] which is wrong in general for the same reason, should be [string, unknown][]
const i = (x: {a: number}) => Object.entries(x);

Feature request: Fix or ignore control flow type narrowing errors in unreachable code

One annoying behaviour with typescript is that control flow type narrowing does not work in unreachable code. Even if the code is unreachable, the compiler will still complain on all the type errors within the unreachable code. Not talking about the unreachable code warning, which is very helpful.

Right now you have to comment out the entire unreachable code block (or try to make a debugger play nice in your environment), which works but seeing the goal of the project is fixing annoying typescript behaviour, I feel like this fits.

Here's the TS bug issue, it was made in 2018 so I'm not holding my breath that there will be progress any time soon.
microsoft/TypeScript#26914

Fixing it is probably not worth, seeing as typescript already warns you that you have unreachable code, having errors inside your warning seems superfluous.

So what I'm suggesting is either
A) ignoring them altogether or
B) converting the errors to warnings inside the unreachable code block.

That way you don't have to comment out everything below the return any time you want to ensure that part of your function executes correctly.

BUG: Importing "filter-boolean" only does not seem to work

When importing the whole ts-reset like following, i get the correct type narrowing from, filter-boolean:

import '@total-typescript/ts-reset/';

Bildschirmfoto 2023-02-24 um 13 21 43

When using only filter-boolean it does not work:

import '@total-typescript/ts-reset/filter-boolean';

Bildschirmfoto 2023-02-24 um 13 22 24

Recommended way to add to a monorepo

Assuming you have a monorepo setup like this, is there a way to add it to the packages/tsconfig and have the types propagate throughout your monorepo? Or does this need to be installed and imported in each package?

I tried adding it to the types array in base.json:

// packages/tsconfig/base.json
{
  "compilerOptions": {
    "types": ["@total-typescript/ts-reset"],
  }
}

But got an error in the other apps whose tsconfigs extend from base.json:

error TS2688: Cannot find type definition file for '@total-typescript/ts-reset'.
  The file is in the program because:
    Entry point of type library '@total-typescript/ts-reset' specified in compilerOptions

Does this repo solves "Using an array union type A[] | B[] gets evaluated to A | B when accessing an element of the array"

This is one of the things that annoys me from typescript.
It was closed as a non issue but I reported it on:
microsoft/TypeScript#52084

Bug Report

Using an array union type A[] | B[] gets evaluated to A | B when accessing an element of the array

๐Ÿ”Ž Search Terms

array union,
union of arrays,
accessing an element,
union of custom typed arrays,
accessing an array element

๐Ÿ•— Version & Regression Information

V3.3.3 to
V4.9.4
(All typecript playground versions)

โฏ Playground Link

Playground link with relevant code

๐Ÿ’ป Code

interface A {
      children:A[]
      a: number
}

interface B {
      children:B[]
      b: number
}

const func = (obj: A[] | B[]):void => {
      obj[0].children = [obj[1]]
      obj[0].children.push(obj[1])
}

๐Ÿ™ Actual behavior

This gives a compilation error

Type '(A | B)[]' is not assignable to type 'A[] | B[]'.
  Type '(A | B)[]' is not assignable to type 'A[]'.
    Type 'A | B' is not assignable to type 'A'.
      Property 'a' is missing in type 'B' but required in type 'A'.(2322)

๐Ÿ™‚ Expected behavior

No errors,
if obj is A[], then obj[1] is of type A and can be assigned to obj[0].children = [ obj[1] ],
else the same applied but with B

Reset `AbortSignal`'s `reason` to `unknown`

AbortController is JavaScript's built-in cancelation interface for asynchronous requests (like fetch).
When aborting, you can provide a "reason" - Typescript types reason as any:

const controller = new AbortController();
const signal = controller.signal;

const fetchData = async () => {
  try {
    const response = await fetch("some-url", { signal });
    // ...
  } catch (e) {
    if (e instanceof Error && e.name === "AbortError") {
      console.log(signal.reason.toUpperCase()); // `signal.reason` is `any`, so no complains here
    }
  }
};

fetchData();
controller.abort(3); // This will throw a TypeError because I'm calling toUpperCase

It seems like "resetting" AbortSignal's reason to unknown is a useful change that is in the spirit of this library.
I'd be glad to open a PR.

Make dynamic require imports return `unknown`

Currently, require faces a similar problem to JSON.parse, where it returns any. Like JSON.parse, I think this would be another great place to reset the return type to be unknown.

I.e.

var require: NodeRequire (id: string) => any

becomes

var require: NodeRequire (id: string) => unknown

Improve filter with type guards

I think the filter could be improved by using the following declaration:

interface Array<T> {
  find<S extends T>(
    predicate: (this: void, value: T, index: number, obj: T[]) => value is S,
    thisArg?: any
  ): S | undefined;
}

This allows to use type-guards as filters and get a well-typed return type (playground link)

Example Usage

const isNumber = (n: any): n is number => typeof n === 'number'
const arr = [1, 2, undefined, null, 'hello']

const numbers = arr.filter(isNumber)
//    ^? const numbers: number[]

Rename package to `ts-reset`

Short package names make installing and finding packages easier. There is already a ts-reset package, but it has few downloads and does not do anything, so you can use the dispute resolution policy to request it. If they ask for an explanation, tell them the package owner is squatting your project's name.

Use tsconfig.json instead of import

Since it's global like lib.dom.d.ts, it makes more sense in the compiler options imho.

{
  "compilerOptions": {},
  "include": ["@total-typescript/ts-reset"]
}

It also avoids having to choose in which TS file to put import "@total-typescript/ts-reset";.

Should potentially unsafe array accessing be handled?

I am opening this issue more as a request for discussion not as an actual feature request as I am not sure if the use case really is worth the hassle of additional type guards.

Currently you are able to access an arbitrary element in an array using either the bracket notation or the at function. In the below case typescript will still evaluate the elements to be of type number even though potentially they are undefined.

  const foo = [1,2,3];

  const bar = foo[5];  // undefined
  const baz = foo.at(-4);  // undefined
  const foobar = foo[2];  // number

This has been biting me multiple times in the past e.g. when using express-xml-bodyparser which implicitly turns children into arrays.
I just feel like arrays usually are accessed in forEach, map or loops with the length fields as limits so that it isn't an issue for 98% of the time and having to introduce additional type guards everywhere might be to much of a drawback.

What do you think? Is it even possible to override the typing of the array getter?

bug: Individual imports not working

Hi Matt,

it seems that the individual entrypoints for the helpers are broken.

For example, considering the following:

import "@total-typescript/ts-reset/array-includes";
import "@total-typescript/ts-reset/fetch";

const users = ["matt", "sofia", "waqas"] as const;

const isUser = (input: string) => {
  if (users.includes(input)) {
    // input is narrowed to "matt" | "sofia" | "waqas"
    console.log(input);
  }
};

fetch("/")
  .then((res) => res.json())
  .then((json) => {
    console.log(json); // any
  });

Shows an error in users.includes and console.log(json) is still any.

However, including the whole library works just fine:

import "@total-typescript/ts-reset";

const users = ["matt", "sofia", "waqas"] as const;

const isUser = (input: string) => {
  if (users.includes(input)) {
    // input is narrowed to "matt" | "sofia" | "waqas"
    console.log(input);
  }
};

fetch("/")
  .then((res) => res.json())
  .then((json) => {
    console.log(json); // any
  });

Package to test:

{
  "name": "tsresettest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@total-typescript/ts-reset": "^0.3.7",
    "typescript": "^4.9.5"
  }
}

CodeSandbox: https://codesandbox.io/s/serene-mountain-rebrlv?file=/src/index.ts

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.