Skip to content

Instantly share code, notes, and snippets.

@toolness
Last active July 11, 2022 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toolness/9643d6103efc0fa8745de12fc61759e8 to your computer and use it in GitHub Desktop.
Save toolness/9643d6103efc0fa8745de12fc61759e8 to your computer and use it in GitHub Desktop.
Extremely ridiculously confusing things about TypeScript

By and large, TypeScript is an incredible tool that I'm very grateful for, but sometimes it really makes me want to tear my hair out.

Narrowing functions WTF

TypeScript 3.1 introduced a breaking change involving narrowing functions that I have no idea how to work around.

Here's one attempt to make an unconstrained generic into something that's vaguely constrained: I want to define a type T in which we don't know what properties it has, but we want to make sure that any properties it does have are booleans.

type ObjWithBooleanValues = {
  [key: string]: boolean;
};

function blarg<T extends ObjWithBooleanValues>(thing: T|((arg: string) => void)): boolean {
  if (typeof(thing) === 'function') {
    // Yay, TS 3.1 actually is OK with this, unlike if T was unconstrained.
    thing('awge');
    return true;
  } else {
    // Except now TS thinks that keys which don't exist are actually booleans. :(
    return thing.totallyNonexistentPropertyThatBizarrelyTypechecks;
  }
}

const notActuallyABooleanEvenThoughTypescriptThinksItIs = blarg({ hello: true });

I have no idea how to convince TypeScript that T is constrained to anything that either isn't a function, or is JSON-serializable, or something else that doesn't also cause the type to do really weird things.

Globals in one file showing up in another WTF

Seriously?

Admittedly this isn't really TypeScript's fault, but the insanity of web development is really getting to me.

@sm3sher
Copy link

sm3sher commented Jul 11, 2022

Your thing.totallyNonexistentPropertyThatBizarrelyTypechecks is not bizarre, it compiles because your generic T extends an ObjWithBooleanValues which accepts any string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment