typescript2.4 - Typescript keyof extra type condition -


i want pass 2 generic condition pass array type field name not accepted second condition.

this method declaration , no problem.

firstordefault<k extends keyof t>(predicate?: (item: t) => boolean, recursiveitem?: k): t; 

above method declaration working want pass array type in recurviseitem field.

i'm trying method declaration doesn't work.

firstordefault<k extends keyof t & t[]>(predicate?: (item: t) => boolean, recursiveitem?: k): t 

how can solve problem?

sample code

let departments : idepartment[] = [     {         name: 'manager',         subdepartments: [             {                 name: 'accountant'             }         ]     } ]  // method declaration , code worked can pass name , subdepartments field pass recursiveitem parameter want t[] type field pass subdepartments. let department = departments.firstordefault(d => d.name == 'accountant', 'subdepartments') console.log(department)  interface array<t> {     firstordefault<k extends keyof t>(predicate?: (item: t) => boolean, recursiveitem?: k): t; }  array.prototype.firstordefault = function(this, predicate, recursiveitem) {     if (!predicate)         return this.length ? this[0] : null;     (var = 0; < this.length; i++) {         let item = this[i]         if (predicate(item))             return item         if (recursiveitem) {             let subitems = item[recursiveitem]             if (array.isarray(subitems)) {                 var res = subitems.firstordefault(predicate, recursiveitem)                 if (res)                     return res             }         }     }     return null; }  interface idepartment {     name?: string,     subdepartments?: idepartment[] } 

i don't think there's great answer. looking type function identifies properties of type t values of type array<t> (or array<t> | undefined since optional properties that). naturally expressed mapped conditional types, not yet part of typescript. in case, make like

type valueof<t> = t[keyof t]; type restrictedkeys<t> = valueof<{   [k in keyof t]: if<matches<t[k],array<t>|undefined>, k, never> }> 

and annotate recursiveitem parameter type restrictedkeys<t> , done. can't that.


the solution i've works give on extending array prototype. (that's bad practice anyway, isn't it?) if okay standalone function first parameter array<t>, can this:

function firstordefault<k extends string, t extends partial<record<k, t[]>>>(arr: array<t>, pred?: (item: t) => boolean, rec?: k): t | null {     if (!pred)         return this.length ? this[0] : null;     (var = 0; < this.length; i++) {         let item = this[i]         if (pred(item))             return item         if (rec) {             let subitems = item[rec]             if (array.isarray(subitems)) {                 var res = firstordefault(subitems, pred, rec)                 if (res)                     return res             }         }     }     return null; } 

in above, can restrict type t partial<record<k,t[]>>, meaning t[k] optional property of type array<t>. expressing restriction on t, type checker behaves you'd like:

firstordefault(departments, (d:idepartment)=>d.name=='accountant', 'subdepartments') // okay firstordefault(departments, (d:idepartment)=>d.name=='accountant', 'name') // error firstordefault(departments, (d:idepartment)=>d.name=='accountant', 'random') // error 

as said, there's no great way take above solution , make work extending array<t> interface, since works restricting t. in theory, express k in terms of t, keyof (t & partial<record<k,t[]>>, typescript not aggressively evaluate intersections eliminate impossible types, still accepts name, though inferred type of name property string & idepartment[] shouldn't exist.

anyway, hope above solution can work you. luck!


edit: see you've solved own problem relaxing different requirement: recursiveitem parameter no longer key name. still think should consider standalone function solution, since works intended , doesn't pollute prototype of array. it's choice, of course. luck again!


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -