/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
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 trying to implement a generic React component, but I cannot make the props typing work correctly:
import type { ComponentPropsWithoutRef, ElementType } from 'react'
type FooProps<T extends ElementType> = ComponentPropsWithoutRef<T> & { Component: T }
export const Foo = <T extends ElementType = 'a'>(props: FooProps<T>) => {
const { Component = 'a' as ElementType, ...restProps } = props
if (Component === 'a') {
// href is of type "any"
// How to make "props" be of type ComponentPropsWithoutRef<'a'>?
const { href } = props
// Type is properly inferred here:
return <Component href="" />
}
return null
}
Thanks in advance for any replies. I'm new to Typescript and looking at migrating a JS app, and before I get too deep I want to make sure I really am supposed to write out every prop parameter twice.
E.g. in JS:
function GameList({ userId, sessionId, opt, mode }) {
...
}
In TS:
type GameListProps = {
userId: number,
sessionId: number,
opt?: any,
mode?: string,
};
function GameList({ userId, sessionId, opt, mode }: GameListProps) {
...
}
Now when I modify this in the future, I have to update two places and keep them in sync.
I assume there's a good reason I'm currently missing? Like why don't we do this instead?
function GameList({
userId: number,
sessionId: number,
opt?: any,
mode?: string,
}) {
...
}
Hi, devs! I've been trying to achieve the following goal, but without success. I want to import object from a third party package, then use the keys as type and export the type. I want to build/compile (it is types only package in monorepo) and then use in other packages. Some of the imports are promises. Is there any good approach to do it? Here is quick pseudo code:
import { someObject } from "awesome-package"
type someType = {
[P in keyof typeof someObject\]: boolean;
}
export { someType }
It seems the documentation suggests they are practically the same, and it's a matter of developer preference. Is that really so, or are there some rare cases where there's an actual difference?
Readonly<Type> example:
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
todo.title = "Hello";
// Cannot assign to 'title' because it is a read-only property.
readonly Properties example:
interface SomeType {
readonly prop: string;
}
function doSomething(obj: SomeType) {
// We can read from 'obj.prop'.
console.log(`prop has the value '${obj.prop}'.`);
// But we can't re-assign it.
obj.prop = "hello";
// Cannot assign to 'prop' because it is a read-only property.
}
For the sake of search: Readonly utility type has an uppercase (capital) R and is used with angle brackets, whereas readonly modifier is lowercase (all small letters) and used like a keyword.
i know its a dumb question but i will ask anyway, imagine you can write code like this :
//math.ts
function add(x: number, y: number): number {
return x + y;
}
//another.ts
import type {add} from './math.ts'
const foo : add
and ts will extract the type definition from add function to foo const , and whenever i made change in add function thats will reflect with errors or warnings in 'another.ts' file 😅
I am searching for an alternative to Nest.js, but I haven't been able to find any framework that is as comprehensive as Nest. I'm looking for a solution that includes features such as Dependency Injection, ORM, Authentication, and Authorization. Are there any good alternatives to Nest or a suitable stack that meets these requirements that you would recommend?
As of now my project uses a .env file for configuration. The problem with that is I get no type inference in my files and also each time I use a variable I have to write process.env.variable
Extending the processEnv
definition of nodeJs namespace
works but still I need to rewrite process.env.variable
each time
I was wondering if there is a way to just use a variable like env.variable
and also get all the typescript features like type inference and intellisense.
Hey all,
I am working on a task in my current organization and have been thrust into the world of TS, React Query and React. I just started to wrap my head around the SDK but do not have the time to understand the tech stack and implement the feature.
I am looking to seek some help online, and preferably someone who can help me in the next 16-20 hrs of me putting this post out.
This is an extremely tiny task but you will be paid for it. Ideally, you could also help me understand few things regarding the same.
Please shoot me a DM/Chat and will connect with you.
Thanks
I'd like to start off by saying this isn't a TypeScript problem, but it can be a TypeScript solution. I'm hoping to find like-minded people who feel the same way about type safety. Currently, it is rather difficult to know exactly what DOM APIs might throw and which ones might not. It would be really nice to have a kind of error map, or at least see in the typescript types what function would call what error (JSDoc "@throws"). I opened a TS feature request. This would allow library developers to easily build off of official error maps, enforcing type safety.
Example: did you know that document.querySelector
will throw an exception for invalid syntax? You might think it would just return null or undefined. It doesn't. I patched a bug in a library a while back because they used querySelector and assumed it wouldn't throw. But why would one think it would throw in the first place? It's not like it tells you that! And where do you find this information? You have to go to MDN or something similar. I don't believe any single rockstar developer can have the whole DOM in their head and know which functions throw. And it's unrealistic to be checking constantly to see if simple APIs like querySelector might throw. There are bound to be mistakes, and I'm sure those mistakes have already propagated largely in the wild web world.
So the solution for me is either:
A) have "@throws" be in the type description (hovering over the function tells you if it may throw, and what type it may throw)
or
B) generate error maps so that developers can create libraries that leverage these, creating proxies that can transform function calls into consumables like (neverthrow)[https://github.com/supermacro/neverthrow], forcing error handling and facilitating a high standard of type safety.
I'll say it again: this isn't a TypeScript problem nor TypeScript's responsibility to fix. But it is a problem, and someone needs to do something about it! And it helps when that someone is official and devs can rely on them to stay up to date.
Following is the working JS code which I'm now trying to migrate to TS. While defining spotifyData, I used this keyword as you can see down below, to set a required condition depending on the boolean isSpotifyConnected.
I've tried using functions instead of using this directly but then it gives other errors or maybe I'm not doing that right. I tried looking into the documentation and that was hard to understand for me. I need two things, a solution for this particular problem and most importantly, how can I understand what's going on here. Can someone suggest some resources?
import mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
isSpotifyConnected: {
type: Boolean,
default: false,
required: true
},
spotifyData: {
type: {
access_token:{
type: String,
required: this.isSpotifyConnected ? true : undefined
},
refresh_token:{
type: String,
required: this.isSpotifyConnected ? true : undefined
},
expires_in:{
type: Number,
required: this.isSpotifyConnected ? true : undefined
},
expiry_time:{
type: Number,
required: this.isSpotifyConnected ? true : undefined
}
},
default : {}
}
});
const User = mongoose.model('User', userSchema);
export default User;
I remember seeing an import (roughly) like this one
import json from './json' as Type.
But I can't find any docs for it
Is there something like this in TS?
Thank you
I want to use typed-scss-modules with module path aliases. I have configured it the tool to put the generated tyoe definitions in the "__generated__" directory. I have followed all their steps. Now I do not get safety if I import the styles using
import styles from "@/styles/Layout.module.scss";
But it works when I use
import styles from "../../styles/Layout.module.scss";
I have the following set in the tsconfig.json
"rootDirs": [".", "__generated__"],
"baseUrl": "src/",
"paths": {
"@/styles/*": ["styles/*"]
}
How do I get the auto generated type definitions to work when using path alias?
TLDR: Check out my new end-to-end type adapter for Express.js: express-typed
I’ve always appreciated the simplicity of Express, but it was created back in 2009, long before TypeScript emerged in 2014. Consequently, type safety wasn’t built into the framework from the start.
While alternatives like trpc exist, they often come bundled with peculiar adapters specific to trpc, not always seamlessly fitting into other setups.
Another option ts-rest and zodios, but they require upfront type definitions imported into both backend and frontend. This approach can be tedious, especially when dealing with dynamic backend types, such as those in Prisma ORM.
When confronted with these challenges in my recent project, I decided to build a custom type adapter for Express.js Router. This solution relies heavily on type declarations, wrapped in a tiny runtime wrapper around Express.Router, that enables type inference (as TypeScript inference primarily operates declaratively: during assignment and return, while Express.Router routes are declared imperatively)
This library was successfully deployed in production with my latest project, and the results were so impressive that I couldn’t resist extracting the type adapter into a separate library to share with you all.
Check out the GitHub repo for more details, and please share any suggestions or issues you encounter!
We've of course seen both. indexOf
returning -1
when the item isn't found, and other instances where null is returned. I see some advantages of null though. Namely that the call-site with typescript will have to check it has been handled more explicitly whereas with -1 I think it may be more error prone from a usage perspective. What do you think? What's the best practice?
EDIT: This problem is fixed. See solution here:
I have installed jest with react testing library in my laravel project. After countless hours of figuring out how to set it up, I am encountering this issue:
Cannot find module '@/Components/Checkbox' or its corresponding type declarations
Here is the code segment where the error is occuring:
import { render } from '@testing-library/react';
import React from 'react';
import CheckBox from '@/Components/Checkbox'; //error
describe('Checkbox', () => {
it('should work as expected', () => {
render(<CheckBox />);
});
});
{
"compilerOptions": {
"allowJs": true,
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"isolatedModules": true,
"target": "ESNext",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"paths": {
"@/": ["./resources/js/"],
"ziggy-js": ["./vendor/tightenco/ziggy"]
}
},
"include": ["resources/js//*.ts", "resources/js//.tsx", "resources/js/**/.d.ts"]
}
const {pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig')
/** u/type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
// mocking assests and styling
'^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/tests/resources/mocks/fileMock.ts',
'^.+\\.(css|less|scss|sass)$': '<rootDir>/tests/resources/mocks/styleMock.ts',
/* mock models and services folder */
'(assets|models|services)': '<rootDir>/tests/resources/mocks/fileMock.ts', },
},
// to obtain access to the matchers.
// setupFilesAfterEnv: ['./tests/resources/setupTests.ts'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
modulePaths: ['<rootDir>'],
testEnvironment: 'jsdom',
};
Here is the file structure:
Frontend components are in `resources/js` and tests are inside `tests/resources`
I looked through countless forums and I am not able to fix this...
I'm using tsc as my compiler, when I build my express project with NODE_ENV set to development
everything builds fine, as it should.
However, when I set it to production
tsc build fails, with error about missing type definitions. For example, @types/cors
or @types/express
. I understand why they are missing. It's because node install doesn't install dev dependencies when NODE_ENV is set to production
, as it should.
Then how am I supposed to build my project for production if tsc build expects dev dependencies? Should I just use NODE_ENV=development
? Is there a problem with my configuration? What am I missing?
My start script:
"start": "npx tsc && node dist/index.js",
My tsconfig.json:
I'm getting into TypeScript and I'm stumped by this puzzle.
To explain what I'm trying to do:
productObject
s, and a key. The function returns all unique values for that key found in the array of objectsHow do I specify the return type of this function?
The product object:
interface ProductObject {
att1: att1Values,
att2: att2Values,
//...
}
Where att1Values = type "valid value 1" | "valid value 2" // | ...
And the function would look like this:
function uniqueVals(objects: ProductObject[], attribute: keyof ProductObject){
const allVals = objects.map(o => o[attribute])
return [... new Set(allVals)]
}
I've tried esbuild, deno, rollup, and, of course, tsc.
My goal is to compile all of my TypeScript files into a single JavaScript file so import/export isn't present. The closest result was from these compiler options:
{
"compilerOptions": {
"target": "es5",
"module": "System", // or "AMD"
"outFile": "transpiled-code/clasp.js",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}
This does output a single file but the platform I deploy my code to cannot interpret the results from "module": "System"
or "module: "AMD"
.
Has anyone dealt with this before?
Hello,
Basically I'm trying to achieve a SQL inner-join between 2 arrays of types that share a common key.
After a lot of tries and googling, I have to admit this is beyond my knowledge, here's how far I got:
public merge<Key extends string | number | symbol,
Value,
Base extends { [key in Key]: Value },
Type1 extends Base,
Type2 extends Base
>(
array1: Type1[],
array2: Type2[],
key: Key
): (Type1 & Type2)[] {
const merged = array1.map((item1) => {
const match = array2.find((item2) => item2[key] == item1[key]);
if (match) {
return { ...item1, ...match };
} else {
return { ...(<Type1>{}), ...(<Type2>{}) };
}
});
return merged;
}
The compiler complains that item2[key] == item1[key] is not possible because the types don't overlap
, but they both extend Base
which contains the same key (atleast I'm hoping it would)
Can you help me with that ? Much appreciated :)
PS: Sorry, this is the first time I post code here. I don't know how to enable syntax highlighting, feel free to guide me !
PS2: I know that the complexity of this algorithm can be improved from n*n to n*log(n) and I will do that obviously, after I fixed the compiling.
Out of these following two pieces of code, which one would you prefer to make part of your code base and why?
type CompareResult = -1 | 0 | 1;
enum CompareResultOptions {
Asc = 1 as CompareResult,
Same = 0 as CompareResult,
Desc = -1 as CompareResult
};
function compareNumbersAscending(a: number, b: number): CompareResultOptions {
if(a > b) {
return CompareResultOptions.Asc;
} else if(a === b) {
return CompareResultOptions.Same;
} else {
return CompareResultOptions.Desc;
}
}
var a = Array.from({length: 100}, _ => Math.floor(Math.random() * 100))
console.log({a});
console.log({sorted: a.sort(compareNumbersAscending)});
I guess the names Asc
, Desc
, and Same
are not good, what do you suggest?
type CompareResult = -1 | 0 | 1;
function compareNumbersAscending(a: number, b: number): CompareResult {
if(a > b) {
return 1;
} else if(a === b) {
return 0;
} else {
return -1;
}
}
var a = Array.from({length: 100}, _ => Math.floor(Math.random() * 100))
console.log({a});
console.log({sorted: a.sort(compareNumbersAscending)});
I came across this page and found this at the top:
This page is a work in progress, congrats on finding it!
I found it hilarious and wanted to share.
Have a nice day!
Hi all,
I have an issue with type narrowing when using union types. I can break down the problem to this simple example:
type OneOfUnion<T, K extends keyof T, V extends T[K]> = T extends { [key in K]: V } ? T : never;
type Animal = {type: 'CAT', livesLeft: number} | {type: 'DOG', name: string}
// Works - type must be CAT and livesLeft is recognized
const cat: OneOfUnion<Animal, 'type', 'CAT'> = {
type: 'CAT',
livesLeft: 7
}
// Fails - animal is not recognized as CAT
function logAnimalDetails<T extends 'CAT' | 'DOG'>(
animal: OneOfUnion<Animal, 'type', T>,
) {
if (animal.type === 'CAT') {
// Error here
console.log(`Cat has ${animal.livesLeft} lives left`)
}
}
I don't quite understand why in the function the type is not recognized. Thank you for pointing me to the right direction :)
For context, what I try to achieve is to assert to my function that two passed arguments share the same discriminator. Something like this:
type OneOfUnion<T, K extends keyof T, V extends T[K]> = T extends { [key in K]: V } ? T : never;
type Animal = {type: 'CAT', livesLeft: number} | {type: 'DOG', name: string}
type Owner = {type: 'CAT', costsForCatfood: number} | {type: 'DOG', costsForDogFood: number}
export function logAnimalDetails<T extends 'CAT' | 'DOG'>(
animal: OneOfUnion<Animal, 'type', T>,
owner: OneOfUnion<Owner, 'type', T>
) {
if (animal.type === 'CAT') {
// Errors since owner is not narrowed correctly
console.log(`Owner spent ${owner.costsForCatfood} for food`)
}
}
Thank you :)
Why is it possible to add arbitrary attributes to an object? This should throw a Typescript error in my opinion.
type Params = {
limit: number;
}
// Does not work
const params: Params = {
limit: 20,
q: "john"
}
// Does work
const spreadParams: Params = {
limit: 20,
...({ q: "john" })
};
console.log(spreadParams.q);
// 'john'
Hey r/typescript!
I've recently developed a library called typed-xlsx which aims to make exporting data to Excel files (xls/xlsx) more straightforward while maintaining strong type safety and an excellent developer experience.
The library wraps around SheetJs but provides a more accessible, high-level API that simplifies many common tasks and enhances features. Key Features Include:
Type-safe Schema Builder: Design spreadsheet schemas with enhanced reliability.
Type-safe Data Serialization & Transformation: Ensure data integrity throughout your workflow.
Shared Type-safe Custom Value Pre-processors: Use shared pre-processors for consistent value transformations across your spreadsheets.
Column Summary: Auto-insert computed summaries for columns to facilitate data analysis.
Complex Row Structures with Auto-Merging: Simplify the creation of complex layouts with automatic row merging and styling.
Easy Default Values Management: Effortlessly manage default values to present your data as intended.
Dynamic Column Selection: Choose which columns to include dynamically when building your tables.
Dynamic Column Mapping with Type-safe Context: Dynamically map columns in a type-safe manner.
Dynamic Cell Styling/Formatting: Apply custom styling and formatting to cells on a per-row basis.
Multi-sheet Support: Create spreadsheets that contain multiple sheets for better data organization.
Multiple Tables Per Sheet Support: Easily manage multiple tables within a single sheet.
Linear or Grid-like Layout for Sheets with Multiple Tables: Choose between linear or grid layouts for sheets that contain multiple tables.
For a comprehensive demonstration of all the capabilities and the API, check out the live demo on the documentation homepage.
This project is open-source, and you can find the repository and detailed documentation here:ed-xlsx on GitHub
I built typed-xlsx to address the complexities and time-consuming aspects of Excel report generation in TypeScript, focusing on speeding up development without sacrificing flexibility or power. I
would love your feedback on the library! Whether it's a feature request, bug report, or general observations, your input would be invaluable to help improve typed-xlsx. Please feel free to contribute to the repo or drop a comment here.
Thank you for checking it out!
Context:
So I created a VERY basic lightbox to pop out images when they are clicked. My page structure is a div with the ID "popup" with a img tag with the id "popupimg" inside, and then the rest of the page has some images with the class "popout".
Problem:
In the script for all this I can't get typescript to correctly type my "images" const. I am trying to get "images" to be a list of all the images with class popout, And if I leave it untyped it works well and good until I try to run my forEach function where the val "img" is typed as a element and not a HTMLelement and so has no style attribute. And every way I try to type the images component gives me other errors.
My attempt:
I found this in the type script handbook it shows an example of "querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;" but I couldn't figure out how to use that in my code. If I try to use HTMLCollectionOf<HTMLImageElement> for my "images" variable I get "Property 'namedItem' is missing in type 'NodeListOf<Element>' but required in type 'HTMLCollectionOf<HTMLImageElement>" and I have no idea what that means.
<script>
function addPopout() {
const images = document.querySelectorAll("img.popout");
const popup = document.getElementById("popup");
const popupimg = document.getElementById("popupimg") as HTMLImageElement;
if (!popupimg.src || !popup) {
throw new Error("The element popup or popupimg wasn't found");
} else {
images.forEach((img: any) => {
img.style.cursor = "zoom-in";
img.addEventListener("click", () => {
popup.classList.toggle("hidden");
popup.classList.toggle("flex");
popupimg.src = img.getAttribute("src");
});
});
popup.onclick = () => {
popup.classList.toggle("flex");
popup.classList.toggle("hidden");
};
}
}
window.addEventListener("load", function () {
addPopout();
});
</script>
<script>
// add mobile support for touch
function addPopout() {
const images = document.querySelectorAll("img.popout");
const popup = document.getElementById("popup");
const popupimg = document.getElementById("popupimg") as HTMLImageElement;
if (!popupimg.src || !popup) {
throw new Error("The element popup or popupimg wasn't found");
} else {
images.forEach((img: any) => {
img.style.cursor = "zoom-in";
img.addEventListener("click", () => {
popup.classList.toggle("hidden");
popup.classList.toggle("flex");
popupimg.src = img.getAttribute("src");
});
});
popup.onclick = () => {
popup.classList.toggle("flex");
popup.classList.toggle("hidden");
};
}
}
window.addEventListener("load", function () {
addPopout();
});
</script>
Thanks for taking the time to read through this, and feedback is appreciated.
I've been learning OOP in JavaScript and find the reliance on prototypes and class syntax, particularly for private properties, to be clunky and awkward. I expected a system more similar to Java's, and now I'm wondering if JavaScript's OOP peculiarities are why TypeScript was developed. Is JavaScript commonly used for OOP, or is TypeScript a better alternative for those looking for a robust, clean OOP experience? What are your thoughts and experiences?