/r/typescript

Photograph via snooOG

TypeScript is a language for application-scale JavaScript development.

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

Resources

Language

Discussion

Rules

  1. Your post should be typescript focused This is r/typescript, lets keep it on topic
  2. No general advertising, promoting services/libs with zero TS utility or closed source projects We get it, you people build awesome things, but this isn't r/sideproject, if you're posting a project it needs to be open source, you need to link to the repo and most importantly given that this is r/typescript it should not only be in typescript but be something that contributes to TS utility (Not just a random lib that happens to be written in TS). Also no general spam of other products or software, even if it's free. Exceptions can be made for software that will be exceptionally useful for typescript development and pipelines, but this is at the moderation teams discretion.
  3. Keep self promotion to a minimum. "It's perfectly fine to be a redditor with a website, it's not okay to be a website with a reddit account." - Confucius
  4. No Recruiters. or recruitment posts, we have a sticky for that, still, it's for redditors only, not professional recruiters.

/r/typescript

138,979 Subscribers

3

Confused about interface merging and how this code passes the type checker

I've been trying to understand how my work's decorator-based mixins work, and it's been a bit of a journey. I've wound up with a piece of code that I don't believe should type check, but it does. So obviously there's something I don't understand.

playground link

In the code below there's no implementation of doSomething and yet the compiler doesn't complain about trying to call it.

interface DoSomething {
  doSomething(param: string): void;
}

interface MyClass extends DoSomething {}

class MyClass {
  constructor() {
    // How does this type check?
    this.doSomething('argument');
  }
}

const c = new MyClass();
// How does this type check?
c.doSomething('argument');

Note that if you rename the interface MyClass the compiler will complain:

interface MyClass1 extends DoSomething {}

class MyClass implements MyClass1 {
  constructor() {
    // Now this is a compiler error
    this.doSomething('argument');
  }
}

So I assume this has something to do with interface merging?

3 Comments
2024/11/02
00:56 UTC

1

How to test null values with Zod validation in TypeScript without type errors?

This is my first time using Zod and I need help testing for null values in my schema validation.

I’m using Zod for validation and have set up a schema and endpoint like this:

app.post(
    '/api/users',
    validateRequest({ 
        body: z.object({
            username: z.string(),
            email: z.string(),
            password: z.string(),
        })
    }),
    async (req, res) => {
        const hashedPassword = await argon2.hash(req.body.password);
        await User.create({
            ...req.body,
            password: hashedPassword,
        });
        res.status(201).send({ message: 'User created' });
    },
);

The problem

I’m trying to write tests to check validation errors when username or other fields are null. Here’s a sample test:

it('should return a 400 status code when username is null', async () => {
    const response = await request(app)
        .post('/api/users')
        .send({
            username: null,
            email: 'user@admin.com',
            password: 'pass4User',
        });
    expect(response.statusCode).toBe(400);
});

However, I’m getting this TypeScript error:

Type 'null' is not assignable to type 'string'

I can’t set username to null in the test without TypeScript complaining. What’s the best way to write tests to check if fields like username, email, etc., are null or invalid?

10 Comments
2024/11/01
19:42 UTC

0

How do you hack on third party dependencies?

TypeScript/JS isn't my main language, so maybe this is obvious. I occasionally need to code dive into GCP libraries. Because my TS reading skills are pretty bad, I'll want to do print debugging or otherwise edit the GCP libraries to check my understanding.

In the past, I was doing LSP goto definition and editing the transpiled JS in my test script's node_modules. This works okay, but the JS is even less readable than the code generated TS. This week I was looking to see if there was a better way.

I would like to:

  • Pull in local copies of all the third party dependencies I want to hack on.
  • Fiddle with the code in a dependency, in a terminal up-arrow and re-run something that runs my test script, repeat.
  • If go to definition or other LSP commands can send me to the Typescript instead of JS, that'd be great.

The dependencies look like:

my-test-script
-- googleapis (https://github.com/googleapis/google-api-nodejs-client)
   |-- google-auth-library (https://github.com/googleapis/google-auth-library-nodejs)
   |-- googleapis-common (https://github.com/googleapis/nodejs-googleapis-common)

I'm using Node 20, TypeScript 5. The test script is usually throwaway and brand new, so I'm open to swapping to other toolchains if they work better.

I tried using npm workspaces from my-test-script with npm init -w ../path/to/dependency. It was surprising to me that after init'ing for every dependency I had to, myself, go to each dependency directory and npm install because the npm init command failed to find a dev dependency. But after I did that I was able to at least run the test script.

My main problem with this setup was that I had to remember to manually rebuild the dependencies after I did each edit. Or, have my test command unconditionally rebuild the three dependencies every time. Or, leave three different tsc watch commands running. npm run -ws watch with tsc -w or nodemon would stop at the first workspace because those tools run in the foreground. This seemed workable, because there's only three dependencies, but not ideal.

Go to (source/type) definition would still bring me to transpiled files and not the TS source.

Most things I've been able to google up has been from the perspective of working in a monorepo where all the dependencies are your own. I haven't personally used lerna or nx or whatever else exists these days.

6 Comments
2024/11/01
16:16 UTC

0

Very weird TypeScript issue.

Okay so I'm trying to build a library which involves forcing certain types for child objects inside of parent objects. I can make everything work fine by putting a generic in the function call. What I'm trying to do is get type safety working in a child without passing a generic directly to it. I want to be able to create a type for the child by passing a type from the parent to the child.

Now here's the thing, with my current setup below, TypeScript makes me pass all the required types to the child, but it also allows me to set types on the child which are not in the `IParent` interface. I guess this has to do with TypeScript's structural type system and saying things are okay if the all the minimum fields are met. What's weird though, if I call a generic function (see **Call 2** below) without passing generics, then TypeScript DOES enforce typesafety for the child. But if I call a function with passing a generic (see **Call 1** below) then TypeScript does allow me to pass extra properties (like "foo") on the child property.

Does anyone know how to set things up to where I can't set extra properties on the child (this is ideal) OR at least how to setup things up to where function call without a generic do allow extra properties?

type GetTypePredicate<T> = T extends (x: unknown) => x is infer U ? U : never;
type TFunction = (...args: any[]) => any;
type TValidatorFn<T> = (arg: unknown) => arg is T;
const isString = (arg: unknown): arg is string => typeof arg === 'string';
type TValidator<T> = (param: unknown) => param is T;


function modify<T>(modFn: TFunction, cb: ((arg: unknown) => arg is T)): ((arg: unknown) => arg is T) {
  return (arg: unknown): arg is T => {
    modFn();
    return cb(arg);
  };
}

type TInferType<U> = {
    [K in keyof U]: (
        U[K] extends TFunction
        ? GetTypePredicate<U[K]>
        : never
    )
}

type TSetupArg<U> = {
    [K in keyof U]: (
        U[K] extends string
        ? TValidatorFn<U[K]>
        : U[K] extends object
        ? ISchema<U[K]> // Here is where type is passed from parent to child
        : U[K]
    )
}

interface ISchema<T> {
    whatever(): boolean;
}

function setup<T, U extends TSetupArg<T> = TSetupArg<T>>(arg: U) {
    return {
        whatever: () => false,
    } as (unknown extends T ? ISchema<TInferType<T>> : ISchema<T>);
}

interface IParent {
    valA: string;
    child: {
        valB: string;
        valC: string;
    }
}

const Final = setup<IParent>({
    valA: isString,
    child: setup({ // If I pass a generic IParent['child'] here, typesafety works, "foo" not allowed
        valB: isString,
        valC: modify<string>(String, isString), // **Call 1** DOES NOT Enforce typesafety for child, "foo" is allowed
        // valC: modify(String, isString), // **Call 2** DOES enforce typesafety for child, "foo" is not allowed
        foo: isString, // extra property 
    })
})
5 Comments
2024/11/01
07:04 UTC

17

Who's hiring Typescript developers November

The monthly thread for people to post openings at their companies.

* Please state the job location and include the keywords REMOTE, INTERNS and/or VISA when the corresponding sort of candidate is welcome. When remote work is not an option, include ONSITE.

* Please only post if you personally are part of the hiring company—no recruiting firms or job boards **Please report recruiters or job boards**.

* Only one post per company.

* If it isn't a household name, explain what your company does. Sell it.

* Please add the company email that applications should be sent to, or the companies application web form/job posting (needless to say this should be on the company website, not a third party site).

Commenters: please don't reply to job posts to complain about something. It's off topic here.

Readers: please only email if you are personally interested in the job.

Posting top level comments that aren't job postings, [that's a paddlin](https://i.imgur.com/FxMKfnY.jpg)

0 Comments
2024/11/01
00:00 UTC

2

[noob] "typescript-coverage-report" wrongly reports 100% of coverage in almost everything.

I'm a seasoned programmer, but I'm very green on anything related to Typescript and it's ecosystem. I do have some experience with JS/node and it's tooling.

I inherit Next.js project developed with Typescript. It has almost no unit tests. So I added the package "typescript-coverage-report" to have a nice report of what is covered and what's not.

Sadly, the report I get says everything its covered at 100% but a handful of files. I guess I'm doing something wrong or there's old configuration getting in the way. I looked at config. files but I don't see anything wrong.

Any advice on what I need to check-out or alternative packages/tools to use is welcome.

10 Comments
2024/10/31
18:33 UTC

3

Live Coding Technical Interview Prep

I have a live coding technical interview to study for. The position is for a Senior QA Engineer. My current team/project uses Playwright and Typescript which is the same as the target company.

I have a lot of automation experience but I'm afraid of the interview being more developer focused.

Any recommendations on what I should focus on, and any resources to get up to speed quickly?

1 Comment
2024/10/31
16:17 UTC

7

Help needed!

So I know all the ts basics and want to level up my ta skills.Can anyone point me to good open source ta repoes with for frontend and backend both.

1 Comment
2024/10/30
23:02 UTC

26

Recommendations for a massive monorepo with slow VSCode Intellisense?

Been working a monorepo recently really slow intellisense (auto importing, type error checking -- the red squiggly, etc).

I was able to optimize a ton of really big type output files which have helped, and also migrated the entire repo (diff packages / apps) to project references.

One app is still pretty slow with intellisense sometimes (5-10 seconds), and it seems to be there's just so many files Typescript has to check.

It has to check over 1.5k files (massive codebase), and seemingly because of that the intellisense is slow.

Just want to double check with people here, am I right here? Is the only way to fix this to restructure the code in the slow app and make the app itself into project references?

Just for some context, here's a UI trace for the slow app:

https://preview.redd.it/93xgepi74yxd1.png?width=3370&format=png&auto=webp&s=3717ea27a21be465ecb3664172ca6b06e28ec686

36 Comments
2024/10/30
19:33 UTC

7

Looking for book recommendations: I have some professional experience, but struggle with technical terms and knowledge

Hi!
As in title: I have 1.5+years of professional experience, but I struggle with technical terms and knowledge. I can use something regulary, but I struggle to answer the question "why". I know this is how you do it, that I should do so-and-so, and yet cannot explain myself properly or in technical language.

I'm currently looking for a job on junior/mid level and just got rejected (as I should, I am ashamed) because of a very, very basic technical question about what's different about arrow function. I almost exclusively use arrow funcions in code, and yet my mind went blank - I couldn't answer.

I think I also know the very root of my problem: I have BCs (which makes my lack of knowledge look even worse), but was taught C/Java/SQL. During my thesis I've discovered that wow, compared to React C/Java/SQL bring me no fun at all - and then I did a few projects on github in React and was very lucky to very quickly get my very first job as a junior frontend developer. So, yeah, I've learnt everything on the go, without any courses, based on some documentation, stack overflow, what my coworkers taught me... and missed whole chunks of knowledge about basics of JS/TS/React sometimes, because I haven't yet needed it at work, even though it's considered basic knowledge in my field.

So I am looking for book recommendations that will help me to fill this gap. Where to look, when I am somewhat comfortable with coding, but yet lack very basic technical terms and knowledge "why" something I do is considered a good practice?

5 Comments
2024/10/29
18:48 UTC

0

How to waste less time on type issues?

Preface So the browser API changes occasionally or i find my self doing PWA's and then i find my self having out of date TS types or maybe the tool/library/whatever i'm using references/uses an older API/type and then this kind of thing happens:

https://stackoverflow.com/questions/60640018/devicemotionevent-request-permission-with-typescript

Now for the real question here.

This is solvable with any easely and i'm inclined to think this is the way, since this type of feature is usually something that will need manual testing over automated testing and it's kindof in the spirit of what TS was made for i think: Too add optional types and makes things easier but otherwise not be in the way.

However i like my types and i like auto completion as i suspect most people here do. :)

Does anyone here have a workflow/tool or other way to avoid having to extend types all the time??

I wanne be productive and setting up types for my types, or hunting down the right type librrary, is the kind of rage inducing busy work that keeps me from wanting to use Typescript more.

16 Comments
2024/10/29
12:00 UTC

14

Can anyone share any production-level experience around Effect TS?

To revisit this old thread, I'm curious to know if anyone has new anecdotes to share around Effect TS.

I'm looking at using it for an upcoming project and it appears quiet promising. Previous opinions from a year ago range from 'run' to 'its the best thing since sliced bread'. Personally, the functional style is pretty attractive in my eyes.

I appreciate the input!

20 Comments
2024/10/29
02:01 UTC

0

I created a typescript-first environment variable validation library.

This has no dependencies and automatically sets up environment variables using the names of your object's keys (converts pascal-case to UPPER_SNAKE_CASE). Typesafety is pulled from the validator function for for that environment variable. You can use your own validator function or use one of the 4 built-in ones.

https://www.npmjs.com/package/jet-env

5 Comments
2024/10/28
18:53 UTC

2

How to get Typescript to narrowing down the type here

Here is a piece of code of mine that responsible for getting the end date

    getEndDate(name: string): string {
        const property = this.pageObj.properties[name];
        if (property.type !== "date") throw new BaseError("Invalid notion data", 400);
        const startDate = property.date?.start;
        const endDate = property.date?.end;
        if (!startDate && !endDate) throw new BaseError("Can't find the date", 400);
        else return (endDate || startDate)!;
    }

The issue I have here is that when I remove the non null assertion, it will give me an error that I can' return type string | undefined, (start date and end date has type string | undefined). But as you can see, I already has a line to check if both are undefined, it will throw an error, but after that line, typescript still not be able to pick this up. One option I seem to have here is type assertion, but I want something more straightforward, a way to actually get typescript to narrow the types down, not to bypass it. Is this possible ?

4 Comments
2024/10/28
14:19 UTC

0

Better mixins in TypeScript: namespaces

I'm developing an interactive data visualization library in TypeScript, and code reuse has always been a challenge for me. Recently, I stumbled upon a simple pattern which I found really useful. I wanted to share this to get some thoughts and perhaps help others who are in a similar situation.

Initially, I had used traditional OOP style, making each of the system's components its own class. However, one thing that I found difficult was implementing shared behavior. For example, I need many of my components to implement the Observer pattern.

I first tried dealing with this using JavaScript's single inheritance, i.e.:

class Foo extends Observer { ... }

However, this quickly became annoying when I wanted to inherit from multiple classes. I explored the functional mixin pattern as recommended in the TypeScript docs, however, I found this pattern quite grotty and difficult to combine with other language features like generics.

Eventually, I heard about Data Oriented Programming/Design and decided to give it a shot. I separated out my class components into plain data interfaces and functional modules (namespaces), and I found this to work surprisingly well. Specifically, I found there's a great synergy with TypeScript's structural typing and JavaScript's dynamic nature.

For example, here's how I implement the Observer pattern. First, I declare an Observer interface, which is just an object with LISTENERS property (I use symbol key to emulate private propety):

// Observer.ts
const LISTENERS = Symbol(`listeners`);
type Cb = () => void

export interface Observer {
  [LISTENERS]: Record<string, Set<Cb>>;
}

Then, I define a namespace which implements all of the functionality of Observer:

// Observer.ts
export namespace Observer {
  export function of<T extends Object>(object: T): T & Observer {
    return { ...object, [LISTENERS]: {} };
  }

  export function listen(observer: Observer, event: string, cb: Cb) {
    const listeners = observer[LISTENERS]
    if (!listeners[event]) listeners[event] = new Set();
    listeners[event].add(cb);
  }

  export function notify(observer: Observer, event: string) {
    for (const cb of observer[LISTENERS][event]) cb();
  }
}

The Observer.of function promotes an arbitrary object to an Observer. The listen and notify functions work as expected (I've added functionality to dispatch on different string-typed events to make the example more realistic/interesting).

The Observer functionality can then be used like so:

// index.ts
import { Observer } from "./Observer"
const dog = Observer.of({ name: `Terry the Terrier` });
Observer.listen(dog, `car goes by`, () => console.log(`Woof!`));
Observer.notify(dog, `car goes by`); // Woof!

This approach has the advantage that it's really easy to make arbitrary objects into Observers and merge multiple mixins together (and, with "private" symbol keys, you don't have to worry about clashes). You also get all of the benefits of type safety - if you try to Observer.notify on an object which isn't an Observer, you'll get a TypeScript error. Generics are really simple too (for example, it's not too difficult to add a T extends string generic to make Observer<T> typed for specific events).

Finally, while you could do most of the stuff above with ES6 modules, I find namespaces better for one reason. Because of declaration merging, you get both the type and the functionality conveniently exported under the same name. If you can't remember some of the functions' names, you can simply write Observer. and the LSP will give you autocomplete, like with a class instance. Also, I find it better to explicitly name things and signal intent rather than relying on import * as Foo from "./Foo" - if one wants to rename the namespace, it's easy to just re-export.

Anyway, what do you think? Are there some things I'm missing? I think namespaces are quite a neat, under-appreciated feature so I wanted to put this out there. Also apologies for the long post, it's hard to summarize all of this succinctly.

9 Comments
2024/10/28
09:54 UTC

2

Transitioning to TS as a C++ developer

Hi all,

Like the title mentioned - I'm interested in transitioning/learning Typescript but not super familiar with JS and coming with extensive C++ background (also decent familiarity with Python).

I know very different languages with different use-cases but my question is for people who are familiar with both - how should I be going about learning it given my background, what are some things to learn more in-depth and how do I know I'm ready to put it in my resume for potential SWE jobs?

6 Comments
2024/10/28
01:22 UTC

1

What is the difference between PropsWithChildren and regular interface.

Suppose I am defining a shape for my props from an api what difference does it make to use say PropsWithChildren instead of interface or type.

I am new with TS .

4 Comments
2024/10/27
16:27 UTC

3

Custom type to only allow values from instances of a class

I have a very hard time trying to get TypeScript to type check custom things a lot of the time

class Test {
  readonly A
  readonly B
  readonly C
  static readonly D = 'Test D'
  static readonly E = 'Test E'

  constructor(readonly name: string) {
    this.A = `${name} A` as const
    this.B = `${name} B` as const
    this.C = `${name} C` as const
  }
}

class Attributes {
  static readonly Test = {
    One: new Test('Foo'),
    Two: new Test('Bar'),
    Three: Test,
  }
}

Now, Attributes.Test.One.A should evaluate to 'Foo A' and Attributes.Test.Three.D to 'Test D' (sorry for the overly generic examples)

I've been bashing my head against this wall for at least 3 hours now but haven't been able to find/figure out a way to create a type that would exclusively accept the values contained in the objects in Attributes.Test

The closest i've gotten so far has only been

type DynamicTestType = Test extends {
  A: infer A
  B: infer B
  C: infer C
} ? A | B | C : never
type StaticTestType = typeof Test.D | typeof Test.E

type TestType = DynamicTestType | StaticTestType

Which just evaluates to

type TestType = `${string} A` | `${string} B` | `${string} C` | 'Test D' | 'Test E'

I'm really lost at this point

7 Comments
2024/10/27
16:00 UTC

84

I decided to share my long list of typescript validator-functions that I use often.

This is not a library, this is just a list of functions I decided to put in a central location so I can copy them to future projects as needed. These functions are in typescript an do both compile-time (with generics) AND runtime validation. Feel free to provide an feedback, make pull requests etc.

https://github.com/seanpmaxwell/ts-validators/blob/master/src/validators.ts

26 Comments
2024/10/26
15:43 UTC

1

No matching export when importing from .d.ts from library

Apparently there are multiple ways of importing a file and a library, despite if it sets its exports declaritively.

Take this:

'@utils/api/ContextMenu': resolvePath(

resolve(primaryDir, 'api/ContextMenu.ts'),

resolve(fallbackDir, 'api/ContextMenu.d.ts')

),

So, when i import it like this, I get the error:

'No matching export in "node_modules/@vencord/types/api/ContextMenu.d.ts" for import "addGlobalContextMenuPatch"'

So since this is in my build file, i cant import it via implimentation file, here is my build script:

https://pastebin.com/ddgzSng5

So, In my index.tsx i import it via:

import { addGlobalContextMenuPatch, GlobalContextMenuPatchCallback, removeContextMenuPatch } from "@utils/api/ContextMenu";

So I need some way to import the implementation from ContextMenu.d.ts but I cant specify that in my build script or it wont be able to find it, but if i do it, again, it doesn't matter what it exports, my imports cant find what I want from it, so how do i fix this?

Upvote2Downvote0Go to comments

0 Comments
2024/10/26
10:21 UTC

1

Type files not being compiled in include, have to add them to files in config separately

My type files aren't being added to the compilation using the `include` in my tsconfig.
I have to separately add them to `files` in order for it to work.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
  },
  "files": ["./src/types/express.session.d.ts", "./src/types/global.d.ts"],
  "include": [
    "./src/**/*",
  ],
  "exclude": ["node_modules/**/*"]
}

I get errors when I remove this line below, why are these files not included in my `include` ?
I tried adding `./src/types/**/*.d.ts` but that's not working either.

  "files": ["./src/types/express.session.d.ts", "./src/types/global.d.ts"],

It's fairly annoying that every time I add a new type file I have to specifiy it into files in order for it to work.
What can I do to add all the files in my types folder without having to specifiy them one by one?

---

I'm using:
- docker: `FROM node:latest`
- nodejs v23.0.0
- ts-node v10.9.0
- nodemon: `nodemon --watch '*' --exec npx ts-node ./src/bin/www.ts`

4 Comments
2024/10/26
09:41 UTC

3

Request for Ideas: Inline Type Annotations for Destructured Object Parameters

This is mostly a 2 AM shower thought thought but I figured I'd ask on here in case anyone had strong opinions or ideas.

TLDR: how can we avoid having to write a and b twice when doing something like this:

const {a, b}: {a: string, b: number} = someObj;

My main motivation for this comes from using Typescript with React, where a common paradigm is to destructure function parameters that are passed in as an object like so:

function Profile({name, age}) {...}

The common methods of adding typing to this are to either add the type right after the destructure:

function Profile({name, age}: {name: string, age: number}) {...}

or to define an interface for the props:

interface IProfileProps {
    name: string,
    age: number
}

function Profile({name, age}: IProfileProps) {...}

The main annoyance with these formats is that modifying/adding a prop requires typing the variable name twice: once in the type definition and once in the object destructure. What are some possible syntaxes TS could adopt to avoid this?

My initial thought was to support something like function Profile({name: string, age: number}), but this conflicts with the syntax for reassigning the result of a destructure to a new variable name like so:

const {name: userName, age: userAge} = userProfile;

Does anyone have any cool ideas for a syntax update to solve this "problem"?

6 Comments
2024/10/26
08:57 UTC

Back To Top