diff --git a/index.html b/index.html index 7fe3b3b..29f91a3 100755 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@
+ function choose<T, P>(a: T, b: P, takeFirst?: false): P;
+ function choose<T, P>(a: T, b: P, takeFirst: true): T;
+ function choose<T, P>(a: T, b: P, takeFirst?: boolean): T | P {
+ if (takeFirst)
+ return a
+ else
+ return b
+ }
+
+ choose('a', 1).includes('a'); // error
+ choose('a', 1) * 2;
+ choose('a', 1, true) * 2; // error
+ choose('a', 1, true).includes('a');
+
+
+ function checkLock<
+ B extends { alwaysUnlocked?: boolean },
+ O extends (B extends { alwaysUnlocked: true } ? {} : { locked: boolean })
+ >(obj: O, options?: B) {
+ return options && options.alwaysUnlocked || !obj.locked
+ }
+
+ checkLock({}); // error
+ checkLock({ locked: false });
+ checkLock({ locked: true, foo: 'bar' });
+
+ checkLock({}, { alwaysUnlocked: false }); // error
+ checkLock({}, { alwaysUnlocked: true });
+ checkLock({ foo: 'bar' }, { alwaysUnlocked: true });
+
+
+ type ColumnProps = {
+ width: number;
+ autoCalculateWidth?: false;
+ } | {
+ width?: undefined;
+ autoCalculateWidth: true;
+ }
+
+ // error
+ const props: ColumnProps = {
+ width: 4,
+ autoCalculateWidth: true,
+ };
+
+
+ function merge<O, T>(data1: O, data2: T): O | T {
+ return {
+ ...data1,
+ ...data2,
+ };
+ }
+
+
+ type Merge<O, T> = Omit<O, keyof T> & T;
+
+ function merge<O, T>(data1: O, data2: T): Merge<O, T> {
+ return {
+ ...data1,
+ ...data2,
+ };
+ }
+
+
+ interface TypeA {
+ type: 'A';
+ foo: string;
+ bar: string;
+ }
+
+ interface TypeB {
+ type: 'B';
+ foo: number;
+ blubb: string;
+ }
+
+ function distinguishType(type: TypeA | TypeB) {
+ if (type.type === 'A') {
+ type.foo.includes('whatever');
+ type.bar;
+ } else {
+ type.blubb.includes('something');
+ type.foo.toFixed(2);
+ }
+ }
+
+
+ const someObj = {
+ a: 'a',
+ b: 'b',
+ 2: 'c',
+ };
+
+ function filterByKeys(keys: (keyof typeof someObj)[]) {
+ keys.map(key => someObj[key]);
+ }
+
+ filterByKeys(Object.keys(someObj)); // error
+
+
+ function getKeysFromObject<
+ T extends {}, K extends string = (keyof T & string)
+ >(object: T): K[] {
+ const keyPredicate = (key: string): key is K =>
+ object.hasOwnProperty(key) && typeof object[key] !== 'undefined' && object[key] !== null;
+
+ return Object
+ .keys(object)
+ .filter<K>(keyPredicate);
+ };
+
+
+ interface SomeInterface {
+ what: string,
+ you: string,
+ }
+
+ const someArray: (SomeInterface | null)[] = [
+ { what: 'ever', you: 'like' },
+ null,
+ { what: 'the fuck', you: 'want' },
+ null,
+ ];
+
+ // error: Signature ... must be a type predicate ?!
+ const filteredArray: SomeInterface[] = someArray.filter<SomeInterface>(value => !!value);
+
+
+ const predicate = (value: SomeInterface | null): value is SomeInterface => !!value;
+
+ const workingArray: SomeInterface[] = someArray.filter(predicate);
+
+
+ const someObj = {
+ a: 'a',
+ b: 'b',
+ 2: 'c',
+ };
+
+ function filterByKeys(keys: (keyof typeof someObj)[]) {
+ keys.map(key => someObj[key]);
+ }
+
+ function getKeysFromObject<
+ T extends {}, K extends string = (keyof T & string)
+ >(object: T): K[] {
+ const keyPredicate = (key: string): key is K =>
+ object.hasOwnProperty(key) && typeof object[key] !== 'undefined' && object[key] !== null;
+
+ return Object
+ .keys(object)
+ .filter<K>(keyPredicate);
+ };
+
+
+ filterByKeys(getKeysFromObject<typeof someObj>(someObj));
+
+
+ function getKeysFromObject<
+ T extends {}, K extends string = (keyof T & string)
+ >(object: T): K[] {
+ const keyPredicate = (key: string): key is K =>
+ object.hasOwnProperty(key) && typeof object[key] !== 'undefined' && object[key] !== null;
+
+ return Object
+ .keys(object)
+ .filter<K>(keyPredicate);
+ };
+
+
+ const testObject = {
+ 2: 'teststring',
+ 'testkey': 2131,
+ 'otherkey': null,
+ 3: null,
+ };
+
+ getKeysFromObject(testObject); // ('testkey' | 'otherkey')[] --- :(
+ getKeysFromObject<typeof testObject, '2' | 'testkey'>(testObject); // meh...
+
+