TypeScript's attempt to replicate Scala's underscore feature has been implemented, but it proves to

I've been working on a personal project for the past 2 years trying to implement Scala's underscore in TypeScript, but haven't been successful. Here is my attempted implementation and its effect.

The only thing that I really care about typing is "Underscore", everything else can be ignored.

const buildUnderscore = (f: any) => (path: any[]): any => new Proxy(f, handler(path));
const handler = (path: any[]) => ({
    get: function(obj: any, prop: any, value: any) {
        return buildUnderscore((a: any) => getAtPath(a, path.concat(prop)))(path.concat(prop));
    }
})
/* takes object A and key path ["a", "b", "c"] -> returns A["a"]["b"]["c"] */
const getAtPath = (obj: any, [head, ...tail]: string[]): any => {
    if(head === undefined) return obj;
    return getAtPath(obj[head], tail);
}


/* Ignore all implementation above i don't care if its typed this is the only thing i care that's typed */
const _: Underscore = buildUnderscore((a: any) => a)([]);


// ConvertKeysToFunctions<GetArgs<Array<T>["map"]>[0]> is what i need
// but there's no way to infer T
// where GetArgs gets the first argument of Array["map"]
// and ConvertKeysToFunctions converts that types keys to function types
type Underscore = <T>(a: T) => T

const data =  [
        {
            child: {
                name: "bob",
                children: ["sue", "john"]
            }
        },
        {
            child: {
                name: "catness",
                children: ["rue", "hew"]
            }
        },
    ]
console.log(data.map(_))  // converts to data.map((a) => a)
console.log(data.map(_.child.children[0]))// converts to: data.map((a) => a["child"]["children"][0])
console.log(data.map(_.child))  // converts to data.map((a) => a["child"])

Answer №1

Regrettably, TypeScript currently lacks the ability to reference a dynamic property name of an object, which hinders the usability and typing of proxies in TypeScript.

The closest workaround is to utilize a lambda expression:

_ => _.foo.bar

If any properties along the path are optional, you may need to employ complex type manipulation techniques similar to those used in my library designed for a similar purpose. However, be aware that using such methods can significantly slow down the compilation process.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The file isn't located in 'rootDir', even though all the details seem to be accurate

I'm currently troubleshooting an issue with one package in my nx monorepo that is causing the error code "TS6059". Interestingly, all other packages are functioning correctly in previous builds. After reviewing my index.ts files, it appears that all ...

When working with TypeScript in Node, the module ""http"" does not have a default export available

const httpModule = require('http'); httpModule.createServer((req, res) => { res.end('Hello World'); }).listen(3000, () => console.log('Server is running on port 3000')); I've installed @types/node but ...

How can we effectively transfer a value from TypeScript/Angular?

I am new to TypeScript and Angular, and I'm struggling with assigning a value to a variable within a function and then using that value outside of the function. In regular JavaScript, I would declare the variable first, define its value in the functio ...

Discovering the best approach to utilizing Font Awesome 6 with React

Required Packages "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.1", "@fortawesome/react-fontawesome": "^0.1.18", "next": " ...

What is the reason behind the failure of a react factory method compilation when extending a typescript class, despite it working perfectly fine on the base class?

As I delve into my lengthy codebase consisting of hundreds of lines, I have managed to narrow down my issue to a concise example. My query pertains to the peculiar behavior exhibited by the Typescript compiler in a specific scenario. The snippet below com ...

A Promise is automatically returned by async functions

async saveUserToDatabase(userData: IUser): Promise<User | null> { const { username, role, password, email } = userData; const newUser = new User(); newUser.username = username; newUser.role = role; newUser.pass ...

In what ways does PROJEN streamline project configuration for infrastructure and application projects?

Exploring PROJEN and AWS CDK has raised questions for me regarding how PROJEN contributes to standardizing project configurations in the context of multiple projects or repositories. While I see its usefulness for a single project or repository through the ...

I'm having trouble viewing the unique Google Map design on my application

I have recently customized Google maps following the guidelines in this documentation: https://developers.google.com/maps/documentation/javascript/styling For styling, I utilized the Cloud tool and opted for the available template instead of using JSON st ...

Removing a value from a hashmap using Typescript - what is the best way to do it?

After successfully implementing a hashmap in typescript following a helpful post, I am facing an issue with removing something from the hashmap. TypeScript hashmap/dictionary interface To add a key to the keys field of my abstract Input class's hash ...

Issue: The CSS loader did not provide a valid string output in Angular version 12.1.1

I am encountering 2 error messages when trying to compile my new project: Error: Module not found: Error: Can't resolve 'C:/Users/Avishek/Documents/practice/frontend/src/app/pages/admin/authentication/authentication.component.css' in &apos ...

Challenges in designing components in Angular 2.0 and beyond

Issue at hand - There are two input controls on the same page, each belonging to separate components. When a value is entered into the first input box, it calculates the square value and updates the second input control accordingly. Conversely, if the v ...

Disable dates that are more than 7 days from the current date using Material UI's Date

How can I restrict users from selecting dates more than 7 days after their initial selection? In the example image provided, the date of January 30th should be disabled for selection. https://i.stack.imgur.com/iTem4.png Below is the code snippet: const ...

What is the way to send custom properties to TypeScript in combination with StyledComponents?

Encountering an error while attempting to implement Styled Components 3 with TypeScript: TS2365: Operator '<' cannot be applied to types 'ThemedStyledFunction<{}, any, DetailedHTMLProps<TableHTMLAttributes<HTMLTableElement>, ...

What is the method to utilize global mixin methods within a TypeScript Vue component?

I am currently developing a Vue application using TypeScript. I have created a mixin (which can be found in global.mixin.js) and registered it using Vue.mixin() (as shown in main.ts). Content of global.mixin.js: import { mathHttp, engHttp } from '@/ ...

Challenge: Visual Studio 2015 MVC6 and Angular 2 compilation issue - Promise name not found

Initially, I've made sure to review the following sources: Issue 7052 in Angular's GitHub Issue 4902 in Angular's GitHub Typescript: Cannot find 'Promise' using ECMAScript 6 How to utilize ES6 Promises with Typescript? Visual ...

I've encountered an error and am unsure of how to fix it

index.ts:5:8 - error TS1192: Module '"D:/Calculator/node_modules/@types/chalk-animation/index"' does not have a default export. 5 import chalkAnimation from "chalk-animation"; ~~~~~~ index.ts:22:1 - error TS1378: To ...

The input tag loses focus after its value is updated using a class method in Angular 8.x

Currently, I am working on integrating a credit card payment method and formatting its number through specific methods. Here is how it is done: HTML <div class="form-group" *ngFor="let formField of cardFields; let cardFieldIndex = index;"> ...

Unable to populate an array with a JSON object using Angular framework

Here is the JSON object I have: Object { JP: "JAPAN", PAK: "PAKISTAN", IND: "INDIA", AUS: "AUSTRALIA" } This JSON data was retrieved as a response from an HTTP GET request using HttpClient in Angular. Now, I want to populate this data into the following ...

How to Hide Parent Items in Angular 2 Using *ngFor

I am dealing with a data structure where each parent has multiple child items. I am trying to hide duplicate parent items, but accidentally ended up hiding all duplicated records instead. I followed a tutorial, but now I need help fixing this issue. I only ...

Choosing Nested TypeScript Type Generics within an Array

I need help with extracting a specific subset of data from a GraphQL query response. type Maybe<T> = T | null ... export type DealFragmentFragment = { __typename: "Deal" } & Pick< Deal, "id" | "registeringStateEnum" | "status" | "offerS ...