/r/typescript
TypeScript is a language for application-scale JavaScript development.
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
Resources
Language
Discussion
/r/typescript
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.
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?
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' });
},
);
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?
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:
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.
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
})
})
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)
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.
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?
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.
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:
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?
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.
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!
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.
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 ?
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 Observer
s 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 namespace
s 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 namespace
s 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.
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?
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 .
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
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
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:
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
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`
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"?