Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Last active September 10, 2023 22:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crutchcorn/5d679f8907ca0271c14a5a723608a789 to your computer and use it in GitHub Desktop.
Save crutchcorn/5d679f8907ca0271c14a5a723608a789 to your computer and use it in GitHub Desktop.
known working examples of TS generics inferencing
function identity<T>(arg: T): T {
return arg;
}
const val = identity(1 as const);
// ^ 1
// ---------------------- Works with classes too ---------------------------------------------
class IdentityWithMeta<T> {
value: T;
touched: boolean = false;
constructor(val: T) {
this.value = val;
}
update(val: T) {
this.touched = true;
}
}
const classVal = new IdentityWithMeta(1 as const);
classVal.value;
// ^ 1
// ---------------------- Works with defaults ---------------------------------------------
function identityWithMeta<T = never>(arg: T): {arg: T, isTouched: boolean} {
return {arg, isTouched: false};
}
const meta = identityWithMeta(1 as const);
meta.arg;
// ^ 1
// ---------------------- Works with classes and defaults too ---------------------------------------------
class IdentityWithMetaAndDelete<T = never> {
value: T | null;
touched: boolean = false;
constructor(val: T) {
this.value = val;
}
update(val: T) {
this.touched = true;
}
delete() {
this.touched = true;
this.value = null;
}
}
const classValWithDelete = new IdentityWithMetaAndDelete(1 as const);
classVal.value;
// ^ 1
// ---------------------- Works with return interface ---------------------------------------------
interface IdentityWithMetaInterfaceRet<T> {
arg: T;
isTouched: boolean;
}
function identityWithMetaReturnInterface<T = never>(arg: T): IdentityWithMetaInterfaceRet<T> {
return {arg, isTouched: false};
}
const metaInterface = identityWithMetaReturnInterface(1 as const);
metaInterface.arg;
// ^ 1
// ---------------------- Works with prop object ---------------------------------------------
function identityMetaProps<T = never>(arg: {value: T, isTouched: boolean}): T {
return arg.value;
}
const propReturn = identityMetaProps({value: 1, isTouched: false} as const);
propReturn;
// ^ 1
// ---------------------- Works with prop interface ---------------------------------------------
interface IdentityMetaPropsInterfaceProp<T> {
value: T;
isTouched: boolean;
}
function identityMetaPropsInterface<T = never>(arg: IdentityMetaPropsInterfaceProp<T>): T {
return arg.value;
}
const propInterfaceReturn = identityMetaPropsInterface({value: 1, isTouched: false} as const);
propInterfaceReturn;
// ^ 1
// ---------------------- Doesn't work ---------------------------------------------
interface Test<T = unknown, O = unknown> {
test: T,
other: O
}
function getTest(args: Test) {
return args;
}
const {test, other } = getTest({
test: "test",
other: "other"
} as const)
// ---------------------- Does work ---------------------------------------------
interface Two<T = unknown, O = unknown> {
one: T,
two: O
}
function getAnotherTest<T, O>(args: Two<T, O>) {
return args;
}
const {one, two } = getAnotherTest({
one: "test",
two: "other"
} as const)
// ---------------------- Does work ---------------------------------------------
interface Three<T = unknown, O = unknown> {
three: T,
four: O
}
function getOneMoreTest<T, O = unknown>(args: Three<T, O>) {
return args;
}
const {three, four } = getOneMoreTest({
three: "test",
four: "other"
} as const)
// ---------------------- Does work ---------------------------------------------
interface Four<T = unknown, O = unknown> {
five: T,
six: O
}
class FourTest<T, O> {
constructor(public opts: Four<T, O>) {
}
returnOpts() {
return this.opts;
}
}
const obj = new FourTest({
five: "test",
six: "other"
} as const)
const {five, six } = obj.returnOpts();
// ---------------------- Does work ---------------------------------------------
interface Five<T = unknown, O = unknown> {
seven: T,
eight: O
}
class FiveTest<T, O = unknown> {
constructor(public opts: Five<T, O>) {
}
returnOpts() {
return this.opts;
}
}
const otherObj = new FiveTest({
seven: "test",
eight: "other"
} as const)
const {seven, eight } = otherObj.returnOpts();
// ---------------------- Does work ---------------------------------------------
interface Five<T = unknown, O = unknown> {
seven: T,
eight: O
nine: O
}
class FiveTest<T, O = unknown> {
constructor(public opts: Five<T, O>) {
}
returnOpts() {
return this.opts;
}
}
const otherObj = new FiveTest({
seven: "test",
eight: "other",
nine: 1
// ^ Complains about not being "other", since `eight` comes first
} as const)
const {seven, eight, nine } = otherObj.returnOpts();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment