question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Inferred constructable types

See original GitHub issue

Suggestion

This issue proposes constructable inferred types. It solves this:

// Ability to construct objects without errors
var obj = {a:1} 
obj.b = 2 // Error: typescript presumes that obj is meant to be the finished type {a:1} - It isn't.
obj.c = 3 // Error

Proposed syntax which says “This is not a finished type. This is a type under construction.”;

var obj : unfinished
var obj : constructable
var obj : inferred

Then:

var obj = {a:1} as unfinished
obj.b = 2
obj.c = 3 
obj // {a:1, b:2, c:3} - OK

var something1 : unfinished
something1 = 1
something1 = "a"
something1 // number | string

var something2 : unfinished
something2 = new myClass
something2.newProp = 1
something2 // myClass & {newProp: 1}

var something3 : unfinished = {a: 1}
something3.b = 2
something3 = "a" // Compile Error! Primitives and objects are incompatible ? - No.
something3 = "a" // Yes:  {a: 1, b: 2} | "a"
something3 // is the subtype of;    {a: number, b: number} | string
something3 // and should be assignable to any type that that has this form or subform

var something4 : unfinished = {a: 1}
something4 = new myClass
something4.newProp = 2
something4 = {c: 3}
something4 = [1]
something4 = "a"
something4 = false
something4 // [1] & {a: 1, c: 3, newProp: 2} & myClass | "a" | false
something4 // which is the subtype of:  Array<number> & {a: number, c: number, newProp: number} & myClass | string | boolean

// Inference should always work without errors. 
// This allows turning a ".js" file into a ".ts" file with 'fewer' issues if "unfinished" is the default for the file. 
// If "unfinished" is the default then the "unfinished" typehint is not needed. That must always be the case in "js" files.
// In a ".js" file:
function getValue(x) {
	var o = {}
	o.a = 1
	if(x == 2) o.b = 2
	else if(x == 3) o = "c"
	else o = x.else
	return o
}
var val = getValue(window.x)
val // {a: 1, b?: 2} | "c" | any

Basically, all object types are combined “&”, all primitives are added as alternatives “|”. An inferred constructable type also means, and the “unfinished” typehilt also says: “The code defines the schema of the type”. So you don’t need an interface or need to keep an interface that you have laying around somewhere in sync with the code that defines it. You can reference the type via type t = typeof theVariableThatHoldsIt.

Current Workaround: Typescript already has the ability to infer a constructed type, but only with the identifier of a function statement and without narrowing. This can be expanded to all variables.

function obj() {}
obj.toJSON = ()=>Object.assign({}, obj) // if serialization is ever wanted - Problem: the "toJSON" property is added.
obj.a = 1
if(x) obj.b = 2
obj // function obj(): { (): void; toJSON(): ...; a: number; b: number; }

🔍 Search Terms

inferred types, constructable type, extendable object

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

–>

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:4
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
brandon942commented, Jan 22, 2022

I’m still learning the irks & quirks of typescript - and btw, I just figured out that type construction for objects is already implemented to some degree - but only within .js files! I have also figured out that you can import types into .js files, not just variables of a type.

import { YesIAmAType } from "./types"
/** @type {YesIAmAType} */
var myVariable

The import is dropped by the bundler. JSdocs offer additional ways to define types inside comments. I don’t know about you guys but I’d rather have useful type annotations in comments than @ts-ignore all over the place.
So as it turns out, there is absolutely no reason at all to work with .ts files.
You lose out on nothing. You get all the productivity gains of api descriptions and auto completion that types are meant to provide - and you avoid all the productivity obstacles of typescript. Like #46941, #47560, this #47559, … and countless other issues + dealing with workaround after workaround after workaround. You also avoid committing your codebase to a syntax that may change, - or exposing yourself to a situation where walking back or migrating to a different typing system in the future with different development tools becomes impossible.
As I’ve mentioned in #46941. A typing system is not supposed to “validate” an entire file and meddle with things that are outside of its area of responsibility. It is supposed to simply provide helpful hints where they are wanted. Nothing more. In that respect typescript’s philosophy is utterly flawed.

2reactions
Josh-Cenacommented, Jan 23, 2022

If you just want helpful hints instead of validation, then JSDoc is the right fit for you!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Understanding infer in TypeScript - LogRocket Blog
The infer keyword is a powerful tool that allows us to unwrap and store types while working with third-party TypeScript code. In this...
Read more >
TS infers unknown return type of my generic function, how do I ...
I've been able to get it to work by forcing types, but I was hoping that there was a way to make it...
Read more >
TypeScript errors and how to fix them
A list of common TypeScript errors and how to fix them.
Read more >
Understanding the TypeScript's type system and some must ...
The process of deducing or inferring type from the initial value is called type inference. TypeScript can infer the type of a variable...
Read more >
TypeScript Cheatsheet, Common Errors, and More
First, lets pretend we have an object that TS can't infer types from, maybe the result of ... TS Classes - Expression is...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found