conditional-type-checks icon indicating copy to clipboard operation
conditional-type-checks copied to clipboard

Add IsAssignable

Open dsherret opened this issue 6 years ago • 9 comments

Similar to IsExact, but less strict.

dsherret avatar Nov 05 '19 15:11 dsherret

For a moment I thought this could be a solution for https://github.com/dsherret/ts-morph/issues/357, and I got so excited :smile: But just to be sure: although all of assertions in this repo are kinda meta-ish, none would be of any help when analyzing code statically, right? You'd still need to actually run the full TypeScript compiler and enable type checking in order to statically determine if two types are assignable to one other, by only looking at source code?

lazarljubenovic avatar Nov 05 '19 17:11 lazarljubenovic

@lazarljubenovic hah, I wish! Yeah, that's still not exposed in the compiler api 😢

dsherret avatar Nov 05 '19 19:11 dsherret

and IsNotAssignable type

smmoosavi avatar Dec 04 '19 16:12 smmoosavi

@smmoosavi wouldn't need that as the API currently supports checking that one of these types resolves to false. For example:

assert<IsNullable<string>>(false);
// or
type doTest = AssertFalse<IsNever<typeof result>>;
// or
type doTest2 = Assert<Has<typeof result, number>, false>;

dsherret avatar Dec 04 '19 17:12 dsherret

It is about readability.

type doTest = AssertTrue<
  IsNotAssignable<
    ActionListener<Animal>,
    ActionListener<Dog>
    >,
  >

or

type doTest = AssertTrue<
  IsAssignable<
    ActionListener<Dog>,
    ActionListener<Animal>
    >,
  >

smmoosavi avatar Dec 04 '19 21:12 smmoosavi

@smmoosavi seems just as readable?

type doTest = AssertFalse<
  IsAssignable<
    ActionListener<Animal>,
    ActionListener<Dog>
  >
>

Should there be IsNotX types for everything to be consistent? Why not just?

type doTest = AssertTrue<
  Not<IsAssignable<
    ActionListener<Animal>,
    ActionListener<Dog>
  >>
>

...though, I don't think that is worth adding.

dsherret avatar Dec 04 '19 21:12 dsherret

potential implementation

true if T is assignable to U

type IsAssignable<T, U> = T extends U ? true : false

example:

type IsAssignable<T, U> = T extends U ? true : false

type C<T> = (c: T) => void 


interface A{ a: string }
interface B{ b: number }
interface AB{a:string,b:number}

type CA = C<A>
type CB = C<B>
type CAB = C<AB>

type x1 = IsAssignable<AB, A> // true 
type x2 = IsAssignable<B, A> // false
type x3 = IsAssignable<A, AB> // false
type x4 = IsAssignable<CA, CAB> // true
type x5 = IsAssignable<CAB, CA> // false

T extends U ? X : Y

The type above means when T is assignable to U the type is X, otherwise the type is Y.

source: https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types

smmoosavi avatar Mar 06 '20 17:03 smmoosavi

type IsAssignable<T, U> = T extends U ? true : false

This isn't a good implementation. With IsAssignable<A | B, B> it gives boolean because T is a bare type parameter and we distribute. A better implementation would be:

type IsAssignable<T, U> = [T] extends [U] ? true : false

Gerrit0 avatar Apr 18 '20 17:04 Gerrit0

https://github.com/unional/type-plus/blob/main/ts/predicates/CanAssign.ts

🌷

unional avatar Apr 02 '22 06:04 unional