Due to the lack of support for partial type inference, calling a function with only one generic parameter results in the defaults being used for the rest. This lack of type-checking allows for issues as seen in your example.
To work around this limitation, we typically use a technique called currying:
function columnFromReferenceTable<T extends Table>() {
return function <
RefCols extends PickColumns<T, ReferenceColumn> = PickColumns<T, ReferenceColumn>,
RefColName extends keyof RefCols = keyof RefCols,
RefCol extends RefCols[RefColName] = RefCols[RefColName],
RefTable extends RefCol["table"] = RefCol["table"],
RefTableColName extends keyof RefTable = keyof RefTable
>(referenceColumn: RefColName, referenceTableColumn: RefTableColName) {
referenceColumn;
referenceTableColumn;
};
}
Simply add another set of parentheses and you're good to go:
columnFromReferenceTable<BarTable>()("foo", "active");
columnFromReferenceTable<BarTable>()("foo", "priority");
columnFromReferenceTable<BarTable>()("foo", "wrong"); // errors
P.S. You can now remove the defaults for your type parameters, and it'll still work.
As noted by another response, my problem stems from TypeScript's current limitation in partial type inference for type arguments. When passing `BarTable` as a type argument without the others, default types are applied, resulting in less strict constraints.
Instead of following the currying method suggested in the other response, I've chosen a different approach to circumvent the issue of partial type inference by introducing the table as an object. This allows for complete inference of all type arguments:
function columnFromReferenceTable<
T extends Table,
RefCols extends PickColumns<T, ReferenceColumn> = PickColumns<T, ReferenceColumn>,
RefColName extends keyof RefCols = keyof RefCols,
RefCol extends RefCols[RefColName] = RefCols[RefColName],
RefTable extends RefCol['table'] = RefCol['table'],
RefTableColName extends keyof RefTable = keyof RefTable
>(table: T, referenceColumn: RefColName, referenceTableColumn: RefTableColName) {
table
referenceColumn
referenceTableColumn
}
const barTable = {} as BarTable
columnFromReferenceTable(barTable, 'foo', 'active') // Valid
columnFromReferenceTable(barTable, 'foo', 'priority') // Valid
columnFromReferenceTable(barTable, 'foo', 'wrong') // Shouldn't be valid
In my library, tables are naturally represented as objects, making this design more user-friendly than using currying. (Playground link)
My journey began with a quick peek at this particular inquiry. However, the approach discussed there utilized custom typing. I am currently iterating over object entries using a for-of loop. Here's a snippet of the values I'm dealing with below. ...
I'm currently using Next.js with TypeScript and Material UI. I have created a component called MyOrders and I am trying to pass data from MyOrders to MyOrderItem. However, I am encountering an issue where I am unable to pass the data to MyOrderItem. ...
One of the components I am working with is a form handling component: import React, { useState } from "react"; export const useForm = (callback: any, initialState = {}) => { const [values, setValues] = useState(initialState); const onCha ...
While attempting to export an interface in a NgModule-declaration, I encountered an error message in my editor (Visual Studio Code) stating: [ts] 'MyInterface' only refers to a type, but is being used as a value here. Below is the code snippet c ...
Looking for guidance on how to use TypeScript interface to define these C# models: public class PageModel { public long Id { get; set; } public string Name { get; set; } public IDictionary<string, FieldModel> Fields { get; set; } } pu ...
When using the Owl Date Time Picker, I noticed that the From and To labels, as well as the Set and Cancel buttons are not being localized. Here is the code snippet I am using to specify the locale: constructor( private dateTimeAdapter: DateTimeAdapter&l ...
My current interface looks like this: interface IWeb3 { ethereum?: MetaMaskInpageProvider; provider?: any; contract?: any; }; I was able to locate the type for ethereum using import { MetaMaskInpageProvider } from "@metamask/providers", ...
I am currently utilizing Angular routing with @angular/router in my Ionic 4 project. I have been attempting to disable the device back-button in Ionic 4, but prevent-default is not working for me. Below is the code snippet from my app.component.ts file: ...
I've encountered some challenges while attempting to link a React class component with my local Apollo cache data. Following the guidelines outlined here, I have run into issues where VSCode and Webpack are generating errors when I try to access data ...
My current challenge involves nesting subscriptions within "subscribe" due to the dependency of some data on the response of the previous subscription. This data flows down the subscription chain until it is stored in an array. Starting with an array of I ...
I have a custom class named Foo with a property called bar that is of type string. class Foo { bar: string } When I use an Arg (from the library type-graphql) without explicitly specifying the type and set the argument type to string, everything works ...
I am currently working on customizing the CKEditor by adding a new button using the ng2-ckeditor plugin. The CKEditor is functioning properly, but I have a specific requirement to implement a button that will insert a Rails template tag when clicked. For ...
Got a couple questions here. I've been using the express get method for a search query and it's fetching the requested tickets without any issues. However, I keep encountering errors even though the method itself is functioning properly. So, my f ...
In my current scenario, I have a state variable defined as: const [budget, setBudget] = React.useState<{ name: string; budget: number | null }[]>(); My goal is to update this state by using a TextField based on the name and value of each input ...
After converting this function to async, I've been encountering issues with type annotations being out of sync: export default async function formatCallRecordsForPGPromise( rawCalldata: CallRecord[], ): Promise<SaveableCallRecord[]> { const ...
I've been working with Angular and grappling with the challenge of validating input fields to prevent white spaces. I decided to experiment with an IF statement, as shown below. Everything seemed to be working smoothly until I encountered an error mes ...
Can you help me figure out how to fix the issue I'm having with loading images in this component? Currently, when I refresh the page, the image does not load properly and appears resized to 1 pixel width. Should I wait for the image to fully load befo ...
I'm having difficulty with tsc recognizing my tsconfig.json file and compiling my .ts files. I keep encountering duplication errors that I'm trying to prevent using my tsconfig.json. Here's what I have: package.json tsconfig.json typings.j ...
The problem I'm facing revolves around the Typescript aspect of an Angular application. I am dealing with a data array that I receive from a subscription. It consists of multiple objects with "titleName" and "ID" properties, but their number is neith ...
Following up on the discussion in How can static methods be invoked in C# 4.0 using dynamic types? Is there a more efficient way to handle duplicated code when working with values like double.MaxValue, int.MaxValue, etc. through the implementation of dyna ...