Typescript: рд╕реБрдЭрд╛рд╡: рдкреНрд░реЙрдкрд░реНрдЯреА рдЯрд╛рдЗрдк рдЯрд╛рдЗрдк рдХрд░реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 28 рдирд╡ре░ 2014  ┬╖  76рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: microsoft/TypeScript

рдордВрд╢рд╛

рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА / рдлреНрд░реЗрдорд╡рд░реНрдХ / рдкреИрдЯрд░реНрди рдореЗрдВ рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЧрдгрдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдмреИрдХрдмреЛрди рдореЙрдбрд▓, рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкрд░рд┐рд╡рд░реНрддрди pluck , ImmutableJS рд╕рднреА рдРрд╕реЗ рддрдВрддреНрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВред

//backbone
var Contact = Backbone.Model.extend({})
var contact = new Contact();
contact.get('name');
contact.set('age', 21);

// ImmutableJS
var map = Immutable.Map({ name: 'Fran├зois', age: 20 });
map = map.set('age', 21);
map.get('age'); // 21

//pluck
var arr = [{ name: 'Fran├зois' }, { name: 'Fabien' }];
_.pluck(arr, 'name') // ['Fran├зois', 'Fabien'];

рд╣рдо рдЙрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЖрдкреА рдФрд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рдмрд╛рдзрд╛ рдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдз рд╣реИрдВред
рд░реАрдврд╝ рдХреА рд╣рдбреНрдбреА рдХреЗ рдореЙрдбрд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП _proxy_ рдХрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ:

interface Contact {
  name: string;
  age: number;
}

pluck рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдПрдХ рдкрд░рд┐рд╡рд░реНрддрди рд╣реИ

T[] => U[]

рдЬрд╣рд╛рдБ U, T prop рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИред

рд╣рд╛рд▓рд╛рдБрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рдВрдмрдВрдз рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЧрддрд┐рд╢реАрд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред

рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди

рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди T[prop] рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдкреЗрд╢ рдХрд░рдирд╛ рд╣реИ рдЬрд╣рд╛рдВ prop рд░рд┐рдЯрд░реНрди рдорд╛рди рдпрд╛ рдкреНрд░рдХрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреИрд╕реЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдПрдХ рддрд░реНрдХ рд╣реИред
рдЗрд╕ рдирдП рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд╕рд╛рде рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рднрд╛рд╖рд╛ рд▓рд┐рдЦ тАЛтАЛрд╕рдХрддреЗ рд╣реИрдВ:

declare module Backbone {

  class Model<T> {
    get(prop: string): T[prop];
    set(prop: string, value: T[prop]): void;
  }
}

declare module ImmutableJS {
  class Map<T> {
    get(prop: string): T[prop];
    set(prop: string, value: T[prop]): Map<T>;
  }
}

declare function pluck<T>(arr: T[], prop: string): Array<T[prop]>  // or T[prop][] 

рдЗрд╕ рддрд░рд╣, рдЬрдм рд╣рдо рдЕрдкрдиреЗ рдмреИрдХрдмреЛрди рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рд╣реА рдврдВрдЧ рд╕реЗ get рдФрд░ set рдХреЙрд▓ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

interface Contact {
  name: string;
  age: number;
}
var contact: Backbone.Model<Contact>;

var age = contact.get('age');
contact.set('name', 3) /// error

prop рд╕реНрдерд┐рд░

рдмрд╛рдзрд╛

рдЬрд╛рд╣рд┐рд░ рд╣реИ рдХрд┐ рд╕реНрдерд┐рд░рд╛рдВрдХ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕реЗ рдЗрдВрдбреЗрдХреНрд╕ рдкреНрд░рдХрд╛рд░ ( string , number , Symbol ) рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХрд╛ рдорд╛рдорд▓рд╛

рдЖрдЗрдП рдПрдХ рдирдЬрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рд╣рдорд╛рд░реЗ Map рдкрд░рд┐рднрд╛рд╖рд╛ рдкрд░:

declare module ImmutableJS {
  class Map<T> {
    get(prop: string): T[string];
    set(prop: string, value: T[string]): Map<T>;
  }
}

рдпрджрд┐ T рдЗрдВрдбреЗрдХреНрд╕реЗрдмрд▓ рд╣реИ, рддреЛ рд╣рдорд╛рд░рд╛ рдирдХреНрд╢рд╛ рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ:

var map = new ImmutableJS.Map<{ [index: string]: number}>;

рдЕрдм get get(prop: string): number рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред

рдкреВрдЫрддрд╛рдЫ

рдЕрдм рдХреБрдЫ рдРрд╕реЗ рдорд╛рдорд▓реЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдореБрдЭреЗ _correct_ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рджрд░реНрдж рд╣реЛрддрд╛ рд╣реИ, рдЪрд▓реЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рд╣рдорд╛рд░реЗ Map рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рдеред
рдпрджрд┐ { [index: string]: number } рдХреЛ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╣рдордиреЗ рджрд┐рдпрд╛ рд╣реЛрдЧрд╛
{ [index: number]: number } рд╕рдВрдХрд▓рдХ рдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдмрдврд╝рд╛рдиреА рдЪрд╛рд╣рд┐рдП?

рдЕрдЧрд░ рд╣рдо рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рдмрдЬрд╛рдп pluck рдЙрдкрдпреЛрдЧ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ:

var contactArray: Contact[] = []
function pluckContactArray(prop: string) {
  return _.pluck(myArray, prop);
}

рдпрд╛ рдПрдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд╕рд╛рде рдЬреЛ рдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрдкрддреНрддрд┐ рдирд╣реАрдВ рд╣реИред
рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП pluck рдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдЙрдард╛рдиреА рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ T[prop] рдЕрдиреБрдорд╛рди рдирд╣реАрдВ рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реИ, T[prop] {} рдпрд╛ any рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП , рдЕрдЧрд░ рдРрд╕рд╛ рд╣реИ рддреЛ рд╕рдВрдХрд▓рдХ рдХреЛ --noImplicitAny рдПрдХ рддреНрд░реБрдЯрд┐ рдЙрдард╛рдиреА рдЪрд╛рд╣рд┐рдП?

Fixed Suggestion help wanted

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

@weswigham @mhegazy , рдФрд░ рдореИрдВ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЗрд╕ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ; рд╣рдо рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЪрд▓рд╛рдП рдЬрд╛ рд░рд╣реЗ рдХрд┐рд╕реА рднреА рдШрдЯрдирд╛рдХреНрд░рдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдПрдВрдЧреЗ, рдФрд░ рдпрд╣ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рд╡рд┐рдЪрд╛рд░ рдХрд╛ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╣реИред

рд╡рд░реНрддрдорд╛рди рд╡рд┐рдЪрд╛рд░:

  • рдПрдХ keysof Foo рдСрдкрд░реЗрдЯрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ Foo рд╕реЗ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдореЛрдВ рдХреА рдпреВрдирд┐рдпрди рдХреЛ рд╣рдерд┐рдпрд╛рдиреЗ рдХреЗ рд▓рд┐рдПред
  • Foo[K] рдкреНрд░рдХрд╛рд░ рдЬреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ K рд▓рд┐рдП рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдорд┐рд▓рди рд╣реИред

рдЗрди рдмреБрдирд┐рдпрд╛рджреА рдмреНрд▓реЙрдХреЛрдВ рд╕реЗ, рдпрджрд┐ рдЖрдкрдХреЛ рдЙрдкрдпреБрдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

function foo<T, K extends keysof T>(obj: T, key: K): T[K] {
    // ...
}

рдпрд╣рд╛рдВ, K keysof T рдХрд╛ рдПрдХ рдЙрдкрдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдПрдХ рд╕рдВрдШ рд╣реИред рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ key рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХреБрдЫ рднреА рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрд╕реЗ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдЙрд╕ рд╢рд╛рдмреНрджрд┐рдХ / рд╢рд╛рдмреНрджрд┐рдХ рд╕рдВрдШ рджреНрд╡рд╛рд░рд╛ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдПрдХ рд╕рд┐рдВрдЧрд▓рдЯрди рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

interface HelloWorld { hello: any; world: any; }

function foo<K extends keysof HelloWorld>(key: K): K {
    return key;
}

// 'x' has type '"hello"'
let x = foo("hello");

рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ keysof рдЕрдХреНрд╕рд░ рдЗрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдореЗрдВ "рджреЗрд░реА" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЙрддреНрд╕реБрдХ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдореИрдВрдиреЗ рдЬреЛ рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдерд╛ (рдпрд╛рдиреА рдЬрд┐рд╕ рдорд╛рдорд▓реЗ рдХреЛ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рд╡рд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрдард┐рди рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ: рдореБрд╕реНрдХрд╛рди :)ред

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рд╕рднреА рдХреЛ рдПрдХ рдЕрджреНрдпрддрди рджреЗрддрд╛ рд╣реИред

рд╕рднреА 76 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

# 394 рдХрд╛ рд╕рдВрднрд╛рд╡рд┐рдд рдбреБрдкреНрд▓рд┐рдХреЗрдЯ

Https://github.com/Microsoft/TypeScript/issues/1003#issuecomment -61171048 рднреА рджреЗрдЦреЗрдВ

@NoelAbrahams рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдирд╣реАрдВ рд╕реЛрдЪрддрд╛ рдХрд┐ рдпрд╣ # 394 рдХрд╛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╣реИ, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рджреЛрдиреЛрдВ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рдмрд╣реБрдд рдкреВрд░рдХ рд╣реИрдВ рдЬреИрд╕реЗ:

 class Model<T> {
    get(prop: memberof T): T[prop];
    set(prop:  memberof T, value: T[prop]): void;
  }

рдЖрджрд░реНрд╢ рд╣реЛрдЧрд╛

@fdecampredon

contact.set(Math.random() >= 0.5 ? 'age' : 'name', 13)

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ?

рдпрд╣ рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдХреЗ рдЕрдВрддрд┐рдо рдкреИрд░рд╛рдЧреНрд░рд╛рдл рд╕реЗ рдХрдореЛрдмреЗрд╢ рдПрдХ рд╣реА рдорд╛рдорд▓рд╛ рд╣реИред рдЬреИрд╕реЗ рдореИрдВрдиреЗ рдХрд╣рд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рд╣рдо рдПрдХ рддреНрд░реБрдЯрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ any T[prop] рд▓рд┐рдП рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рджреВрд╕рд░рд╛ рд╕рдорд╛рдзрд╛рди рдЕрдзрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рд╣реИ

рд╢рд╛рдирджрд╛рд░ рдкреНрд░рд╕реНрддрд╛рд╡ред рд╕рд╣рдордд, рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╕реБрд╡рд┐рдзрд╛ рд╣реЛрдЧреАред

@fdecampredon , рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╣реИред рджрд╛рди рд╕реЗ рдЯрд┐рдкреНрдкрдгреА рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрдЦреЗрдВ рдЬрд┐рд╕рдореЗрдВ membertypeof рд▓рд┐рдП рд╕реБрдЭрд╛рд╡ рд╣реИред

IMO рдпрд╣ рд╕рдм рдПрдХ рд╕рдВрдХреАрд░реНрдг рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИред

@NoelAbrahams рдпрд╣ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИред

  • memberof T рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдЬреЛ рдХреЗрд╡рд▓ T рдЙрджрд╛рд╣рд░рдг рдХреА рд╡реИрдз рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
  • T[prop] T рдХреА рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдирд╛рдорд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ prop рддрд░реНрдХ / рдЪрд░ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдПрдХ brifge рд▓рд┐рдП рдирд╣реАрдВ рд╣реИ memberof рдХреЗ рдкреНрд░рдХрд╛рд░ prop рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдкреИрд░рд╛рдореАрдЯрд░ memberof T ред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореИрдВ рдЯрд╛рдЗрдк рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдорд╛рди рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рдореГрджреНрдз рдкреНрд░рдгрд╛рд▓реА рд░рдЦрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдСрдкрд░реЗрдЯрд░ рдПрдХ рдЕрдЪреНрдЫреА рд╢реБрд░реБрдЖрдд рдХреЗ рд╕рд╛рде-рд╕рд╛рде memberof ред

рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рдФрд░ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИред рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрднреА рддрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ-рд╣реИрд╡реА рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдмрд╣реБрдд рдорджрдж рдХрд░реЗрдЧрд╛ред

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ-рд╣реИрд╡реА рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ

рд╕рдЪред рдлрд┐рд░ рднреА рдпрд╣ рддрдереНрдп рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕реБрдЭрд╛рд╡ рд╣реИред

рдЕрднреА рддрдХ рдФрд░ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдмрд╣реБрдд рдХреБрдЫ рдорджрдж рдХрд░реЗрдЧрд╛ [рдЯрд╛рдЗрдкрд┐рдВрдЧ-рд╣реИрд╡реА рдлреНрд░реЗрдорд╡рд░реНрдХ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП]

рдЙрд╕ рдкрд░ рдпрдХреАрди рдирд╣реАрдВ рд╣реИред рдЙрдкрд░реНрдпреБрдХреНрдд рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдЫрджреНрдо-рд╡рд╕реНрддреБ рдкреИрдЯрд░реНрди рдХреЗ рдмрдЬрд╛рдп рдЯреБрдХрдбрд╝рд╛-рдЯреБрдХрдбрд╝рд╛ рдФрд░ рдХреБрдЫ рд╣рдж рддрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд▓рдЧрддрд╛ рд╣реИред рдореИрдВ # 1003 рдХреА рддрд░реНрдЬ рдкрд░ рдореИрдЬрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдзрд┐рдХ рд╕рдордЧреНрд░ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ред

1003 рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реИ рдХрд┐ any рдПрдХ рдЧреЗрдЯреНрдЯрд░ рдХреЗ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВред рдпрд╣ рдкреНрд░рд╕реНрддрд╛рд╡ рд╢реАрд░реНрд╖ рдкрд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдХрд┐ рдореВрд▓реНрдп рдкреНрд░рдХрд╛рд░ рдХреЛ рднреА рджреЗрдЦрдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЬреЛрдбрд╝рдХрд░ - рдорд┐рд╢реНрд░рдг рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╣реЛрдЧрд╛:

declare module ImmutableJS {
  class Map<T> {
    get(prop: memberof T): T[prop];
    set(prop: memberof T, value: T[prop]): Map<T>;
  }
}

@spion , рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдорддрд▓рдм # 394 рд╣реИ? рдпрджрд┐ рдЖрдк рдЖрдЧреЗ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдереЗ рддреЛ рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЗрдЦреЗрдВрдЧреЗ:

рдореИрдВрдиреЗ рд╡рд╛рдкрд╕реА рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрд╛ рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдФрд░ рд╕рдордЧреНрд░ рд╕реБрдЭрд╛рд╡ рдХреЛ рдмрд╣реБрдд рдмрдбрд╝рд╛ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ред

рдпрд╣ рдореЗрд░рд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╡рд┐рдЪрд╛рд░ рдерд╛ рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВред рдпрджрд┐ memberof T рдХрдИ рддрд░реНрдХ рд╣реИрдВ, рддреЛ рдХреМрди рд╕рд╛ membertypeof T рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ?

get(property: memberof T): membertypeof T;
set(property: memberof T, value: membertypeof T);

рдпрд╣ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ "рдореИрдВ рдХрд┐рд╕ рддрд░реНрдХ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ" рд╕рдорд╕реНрдпрд╛, рд▓реЗрдХрд┐рди membertypeof рдирд╛рдо рдЧрд▓рдд рд▓рдЧрддрд╛ рд╣реИ рдФрд░ рдСрдкрд░реЗрдЯрд░ рдХреЗ рдХрд┐рд╕реА рдкреНрд░рд╢рдВрд╕рдХ рдХреЛ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЛ рд▓рдХреНрд╖рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

get(property: memberof T): membertypeof property;
set(property: memberof T, value: membertypeof property);

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдмреЗрд╣рддрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

get(property: memberof T is A): A;
set(property: memberof T is A, value: A)

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдорд╣рд╛рди рд╕рдорд╛рдзрд╛рди рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдЕрдВрддрд┐рдо рд╕реБрдЭрд╛рд╡ рдореЗрдВ рд╕рднреНрдп рдХреНрд╖рдорддрд╛ рд╣реИред

OK @NoelAbrahams # 394 рдореЗрдВ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдереА рдЬреЛ рдХрдореЛрдмреЗрд╢ рдЙрд╕реА рдЪреАрдЬрд╝ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реА рдереА рдЬреЛ рдпрд╣ рдереАред
рдЕрдм рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ T[prop] рд╢рд╛рдпрдж рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рд╕реНрддрд╛рд╡реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реИ, рдФрд░ рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдореЗрдВ рд╢рд╛рдпрдж рдереЛрдбрд╝рд╛ рдЖрдЧреЗ рдЬрд╛рддрд╛ рд╣реИред
рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЗрд╕реЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдкрдХреНрд╖рдкрд╛рддреА рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд▓рд┐рдЦрдиреЗ рд╡рд╛рд▓рд╛ рд╣реВрдВ;)ред

@fdecampredon , рдЕрдзрд┐рдХ

@ рдиреЛрдПрд▓ рдПрдмреНрд░рд╛рд╣рд╛рдореНрд╕ рдЙрдлрд╝, рдореБрдЭреЗ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛ рдпрд╛рдж рдЖ рдЧрдпрд╛ред рдпрдХреАрди рд╣реИ, рд╡реЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рдорддреБрд▓реНрдп рд╣реИрдВ (рдпрд╣ рдПрдХ рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдкреЗрд╢ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ рдпрд╛ рдирд╣реАрдВ рднреА рд╣реЛ рд╕рдХрддреА рд╣реИ)

рдлреНрд▓реЛ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдереЛрдбрд╝рд╛ рдордЬрдмреВрдд рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА рдФрд░ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ рддрджрд░реНрде рдкреНрд░рдХрд╛рд░ рд╕рдВрдХреАрд░реНрдгрддрд╛ рдХреЗ рд╕рд╛рде рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реЛрдЧрд╛ред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд╣рдо get(prop: string): Contact[prop] рд╕рд╛рде рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ, рд╕рдВрднрд╡ рдУрд╡рд░рд▓реЛрдбрд┐рдВрдЧ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рд╣реИ:

interface Map {
  get(prop : string) : Contact[prop];
}

// is morally equivalent to 

interface Map {
  get(prop : "name") : string;
  get(prop : "age") : number;
}

& рдкреНрд░рдХрд╛рд░ рдСрдкрд░реЗрдЯрд░ (рдЪреМрд░рд╛рд╣реЗ рдкреНрд░рдХрд╛рд░) рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рдХреЛ рдорд╛рдирддреЗ рд╣реБрдП, рдпрд╣ рдЗрд╕рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ

interface Map {
   get : (prop : "name") => string & (prop : "age") => number;
}

рдЕрдм рдЬрдм рд╣рдордиреЗ рдЕрдкрдиреЗ рдЧреИрд░-рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЗ рдХреЛ рдХреЗрд╡рд▓ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрдкрдЪрд╛рд░ (рдХреЛрдИ [prop] ) рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд╣рдо рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдкреНрд░рд╢реНрди рдХреЛ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХреБрдЫ рд╣рдж рддрдХ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред рд╣рдо рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдбрдореА рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ $MapProperties , $Name рдФрд░ $Value рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рдХреЗрд╡рд▓ рдЯрд╛рдЗрдк рдкрд░реАрдХреНрд╖рдХ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реБрдП рдХреЗрд╡рд▓ рдЯрд╛рдЗрдк рдПрдХреНрд╕рдкреНрд░реЗрд╢рди (рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рд╕рд┐рдВрдЯреИрдХреНрд╕) рдХреА рдЕрд╡рдзрд┐ рдореЗрдВ рд╣рдорд╛рд░реЗ рдЙрддреНрдкрдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред рдХрд┐ рдХреБрдЫ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

class Map<T> {
   get : $MapProperties<T, (prop : $Name) => $Value>
   set : $MapProperties<T, (prop : $Name, val : $Value) => void>
}

рдпрд╣ рдЬрдЯрд┐рд▓ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЯреЗрдореНрдкреНрд▓реЗрдЯрд┐рдВрдЧ рдпрд╛ рдЧрд░реАрдм рдЖрджрдореА рдХреЗ рдЖрд╢реНрд░рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд╛рд╕ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдореВрд▓реНрдпреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдЯрд╛рд▓рд╛ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдПрдХ рдЕрдиреНрдп рдХреНрд╖реЗрддреНрд░ рдЬрд╣рд╛рдВ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдЯрд╛рдЗрдк рдХреА рдЧрдИ рд╡рд╕реНрддреБ рдХреЗ рдЧреБрдгреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ:

interface Env {
 // pretend this is an actually interesting type
};

var actions = {
  action1: function (env: Env, x: number) : void {},
  action2: function (env: Env, y: string) : void {}
};

// actions has type { action1: (Env, number) => void; action2: (Env, string) => void; }
var env : Env = {};
var boundActions = {};
for (var action in actions) {
  boundActions[action] = actions[action].bind(null, env);
}

// boundActions should have type { action1: (number) => void; action2: (string) => void; }

рдЗрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рд╕реЗ рдХрдо рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рд╕рдВрднрд╡ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП ( for рд▓реВрдк рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рд╣реИ), рд▓реЗрдХрд┐рди рдпрд╣ рднреА рд╕рдВрднрд╡рддрдГ рдХрд╛рдлреА рдЦрд┐рдВрдЪрд╛рд╡ рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЕрдЧрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рдЙрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдмрд╣реБрдд рдлрд╛рдпрджрд╛ рд╣реЛрдЧрд╛, https://github.com/facebook/react/issues/3398 рджреЗрдЦреЗрдВ

рдЬреИрд╕реЗ https://github.com/Microsoft/TypeScript/issues/1295#issuecomment -64944856, рдЬрдм рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрдиреНрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рджреНрд╡рд╛рд░рд╛ рдЖрдкреВрд░реНрддрд┐ рдХреА рдЬрд╛рддреА рд╣реИ, рддреЛ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рд╣реЙрд▓реНрдЯрд┐рдВрдЧ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХрд╛рд░рдг рдЬрд▓реНрджреА рд╕реЗ рдЯреВрдЯ рдЬрд╛рддреА рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХреНрдпрд╛ рдИрдПрд╕ 6 рдкреНрд░рддреАрдХ рд╕рдорд╕реНрдпрд╛ (# 2012) рд╕реЗ рд╕реАрдЦрдиреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХрд╛ рдПрдХ рдореВрд▓ рд╕рдВрд╕реНрдХрд░рдг рдЕрднреА рднреА рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?

рдордВрдЬреВрд░ рдХреАред

рд╣рдо рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрднрд╡ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдпреЛрдЧрд┐рдХ рд╢рд╛рдЦрд╛ рдореЗрдВ рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред

рдмрд╕ рдпрд╣ рд╕реЛрдЪрдХрд░ рдХрд┐ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд╛ рдХреМрди рд╕рд╛ рд╕рдВрд╕реНрдХрд░рдг рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реИ? Ie рдХреЙрд▓ рд╕реНрдерд▓ рдкрд░ T[prop] рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЙрддреНрд╕реБрдХрддрд╛ рд╕реЗ рдПрдХ рдареЛрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдХреНрдпрд╛ рдпрд╣ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирдпрд╛ рд░реВрдк рдмрдирдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реИ?

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ # 3779 рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдПрдХ рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рдФрд░ рдХрдо рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

interface Map<T> {
  get<A>(prop: $Member<T,A>): A;
  set<A>(prop: $Member<T,A>, value: A): Map<T>;
}

рдпрд╛ рдпрд╣ A рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╣реИ?

рдХреЗрд╡рд▓ рдпрд╣ рдХрд╣рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдореИрдВрдиреЗ рдЗрдореНрдпреВрдЯреЗрдмрд▓рдЬреЗрдПрд╕ рдХреЗ рд╕рд╛рде рдЯреАрдПрд╕ рдПрдХреАрдХрд░рдг рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдХреЛрдбреЗрди рдЯреВрд▓ рдмрдирд╛рдпрд╛, рдЬрдмрдХрд┐ рд╣рдо рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╛рдзрд╛рди рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ: https://www.npmjs.com/package/tsimmutableред рдпрд╣ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬреНрдпрд╛рджрд╛рддрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рд╢рд╛рдпрдж рдпрд╣ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░реЗрдЧрд╛ред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдпрд╣ рдиреЛрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдХрд┐ рд╕рджрд╕реНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдзрд╛рди ImmutableJS рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ:

interface Profile {
  firstName: string 
}

interface User {
  profile: Profile  
}

let a: Map<User> = fromJS(/* ... */);
a.get('profile') // Type will be Profile, but the real type is Map<Profile>!

@ s-panferov рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ:

interface ImmutableMap<T> {
    get<A extends boolean | number | string>(key : string) : A;
    get<A extends {}>(key : string) : ImmutableMap<A>;
    get<E, A extends Array<any>>(key : string) : ImmutableList<E>;
}

interface Profile {

}

interface User {
    name : string;
    profile : Profile;
}

var map : ImmutableMap<User>;

var name = map.get<string>('name'); // string
var profile = map.get<Profile>('profile'); // ImmutableMap<Profile>

рдпрд╣ DOM рдиреЛрдбреНрд╕ рдпрд╛ рджрд┐рдирд╛рдВрдХ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдмрд╛рд╣рд░ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдЙрдиреНрд╣реЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред https://github.com/facebook/immutable-js/wiki/Converting-from-JS-objects

рдзреАрд░реЗ-рдзреАрд░реЗ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреЗ рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рдХрд░рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ, рдФрд░ рдлрд┐рд░ рдзреАрд░реЗ-рдзреАрд░реЗ рдЗрд╕реЗ рд╡рд╣рд╛рдВ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╣реИред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдореЗрдВ рдПрдХ рдРрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдХрд┐рд╕реА рднреА рдЧреИрд░-рдЖрджрд┐рдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдореВрд▓реНрдп рд▓реМрдЯрд╛рддрд╛ рд╣реИ:

function getProperty<T extends object>(container: T; propertyName: string) {
    return container[propertyName];
}

рдЕрдм рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЯрд╛рд░рдЧреЗрдЯ рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рд╣реЛ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЬреЗрдиреЗрд░рд┐рдХ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

function getProperty<T extends object, P>(container: T; propertyName: string) {
    return <P> container[propertyName];
}

рддреЛ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдРрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛:

class C {
    member: number;
    static member: string;
}

let instance = new C();
let result = getProperty<C, typeof instance.member>(instance, "member");

рдФрд░ result рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рд╕реЗ number рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХреЙрд▓ рдореЗрдВ 'рд╕рджрд╕реНрдп' рдХрд╛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕рдВрджрд░реНрдн рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ: рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рдПрдХ _literal_ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рдЬреЛ рд╣рдореЗрд╢рд╛ рд▓рдХреНрд╖реНрдп рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рдЗрд╕ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдЗрди рджреЛрдиреЛрдВ рдХреЛ рдПрдХрд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдХреЗрд╡рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред

рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рдпрд╣ рджреЗрдЦрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдПрдХ _generic рдкреИрд░рд╛рдореАрдЯрд░_ рдХреЗ рд░реВрдк рдореЗрдВ рднреА рдХрд╛рд░реНрдп рдХрд░реЗрдЧреА, рдФрд░ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ (рдЕрдиреНрдп рдорд╛рдорд▓реЗ рдЪреБрдкрдЪрд╛рдк рдЗрд╕рдХреЗ рдореВрд▓реНрдп рдХреА рдЕрдирджреЗрдЦреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрдм рддрдХ рдХрд┐ рд░рдирдЯрд╛рдЗрдо рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХрд╛ рдХреЛрдИ рд░реВрдк рдЙрдкрд▓рдмреНрдз рди рд╣реЛ)ред рддреЛ рд╢рдмреНрджрд╛рд░реНрде рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдз рдХреЛ рджрд░реНрд╢рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рддрд░реАрдХрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:

function getProperty<T extends object, PName: string = propertyName>(container: T; propertyName: string) {
    return <T[PName]> container[propertyName];
}

рдФрд░ рдЕрдм рдХреЙрд▓ рдХреА рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:

let instance = new C();
let result = getProperty<C>(instance, "member");

рдЬреЛ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рд╣рд▓ рдХрд░реЗрдЧрд╛:

let result = getProperty<C, "member">(instance, "member");

рд╣рд╛рд▓рд╛рдБрдХрд┐, C рдореЗрдВ member рдирд╛рдордХ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдФрд░ рд╕реНрдерд┐рд░ рд╕рдВрдкрддреНрддрд┐ рд╣реЛрддреА рд╣реИ, рдЙрдЪреНрдЪ-рдкреНрд░рдХрд╛рд░ рдХреА рд╕рд╛рдорд╛рдиреНрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ T[PName] рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред рдЪреВрдБрдХрд┐ рдпрд╣рд╛рдБ рдЗрд░рд╛рджрд╛ рдЕрдзрд┐рдХрддрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдЧреБрдгреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╣реИ, typeon рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд T[PName] рд░реВрдк рдореЗрдВ рд╢рдмреНрджрд╛рд░реНрде рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреБрдЫ рд▓реЛрдЧ рдХрд░рддреЗ рд╣реИрдВред _value reference_, рдЬрд░реВрд░реА рдирд╣реАрдВ рдХрд┐ рдПрдХ рдкреНрд░рдХрд╛рд░:

function getProperty<T extends object, PName: string = propertyName>(container: T; propertyName: string) {
    return <typeon T[PName]> container[propertyName];
}

(рдпрд╣ рддрдм рднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдЬрдм T рдПрдХ рд╕рдВрдЧрдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛ, рдЬреИрд╕рд╛ рдХрд┐ typeon рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ)

рд╕реНрдереИрддрд┐рдХ рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕реНрд╡рдпрдВ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЛ typeof C рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

let result = getProperty<typeof C>(C, "member"); // Note it is called with the constructor object

(рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ typeon (typeof C) typeof C рд╣рд▓ рд╣реЛрддрд╛ рд╣реИ рдЗрд╕рд▓рд┐рдП рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛)
result рдЕрдм рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рд╕реЗ string ред

рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдкрддреНрддрд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

type PropertyIdentifier = string|number|Symbol;

function getProperty<T extends object, PName: PropertyIdentifier = propertyName>(container: T; propertyName: PropertyIdentifier) {
    return <typeon T[PName]> container[propertyName];
}

рддреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

  • рд╢рд╛рдмреНрджрд┐рдХ рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВред
  • рдЙрди рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреЛ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХреЛрдВ рдХрд╛ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рджреЗрдВред
  • рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреА рдЬреЗрдирд░рд┐рдХ рдХреЗ рдПрдХ рдлрд╛рд░реНрдо рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВред
  • _Generic_ рдкреНрд░рдХрд╛рд░ рдкрд░ рд╢рд╛рдмреНрджрд┐рдХ рдЬреЗрдиреЗрд░рд┐рдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВред

рд╕рдорд╕реНрдпрд╛ рдкрд░ рдкреБрдирд░реНрд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛

рдЕрдм рд╣рдо рдореВрд▓ рд╕рдорд╛рдзрд╛рди рдкрд░ рд╡рд╛рдкрд╕ рдЖрддреЗ рд╣реИрдВ:

function getProperty<T extends object, P>(container: T; propertyName: string) {
    return <P> container[propertyName];
}

рдЗрд╕ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдлрд╛рдпрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдкрде рдирд╛рдореЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕рд╛рдиреА рд╕реЗ рдмрдврд╝рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рди рдХреЗрд╡рд▓ рдкреНрд░рддреНрдпрдХреНрд╖ рдЧреБрдг, рдмрд▓реНрдХрд┐ рдиреЗрд╕реНрдЯреЗрдб рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдЧреБрдг:

function getPath<T extends object, P>(container: T; path: string) {
    ... more complex code here ...

    return <P> resultValue;
}

рдФрд░ рдЕрдм:

class C {
    a: {
        b: {
            c: string[];
        }
    }
}
let instance = new C();
let result = getPath<C, typeof instance.a.b.c>(instance, "a.b.c");

result рд╕рд╣реА рдврдВрдЧ рд╕реЗ string[] рдпрд╣рд╛рдБ рдорд┐рд▓реЗрдЧрд╛ред

рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдиреЗрд╕реНрдЯреЗрдб рд░рд╛рд╕реНрддреЛрдВ рдХрд╛ рднреА рд╕рдорд░реНрдерди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП? рдХреНрдпрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧреА рдпрджрд┐ рдЙрдиреНрд╣реЗрдВ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╕рдордп рдХреЛрдИ рдСрдЯреЛ-рдкреВрд░реНрддрд┐ рдЙрдкрд▓рдмреНрдз рди рд╣реЛ?

рдЗрд╕рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдЕрд▓рдЧ рд╕рдорд╛рдзрд╛рди рд╕рдВрднрд╡ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рджреВрд╕рд░реА рджрд┐рд╢рд╛ рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдореВрд▓ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдкрд░ рд╡рд╛рдкрд╕:

function getProperty<T extends object, P>(container: T; propertyName: string) {
    return <P> container[propertyName];
}

рджреВрд╕рд░реА рджрд┐рд╢рд╛ рд╕реЗ рдЗрд╕реЗ рджреЗрдЦрддреЗ рд╣реБрдП, рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рд╕реНрд╡рдпрдВ рд▓реЗрдирд╛ рдФрд░ рдЗрд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реИ:

function getProperty<T extends object, P>(container: T; propertyName: string = @typeReferencePathOf(P)) {
    return <P> container[propertyName];
}

@typeReferencePathOf рдЕрд╡рдзрд╛рд░рдгрд╛ рдореЗрдВ nameOf рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рд╛рдкреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн typeof instance.member (рдпрд╛ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ typeon C.member ) рд▓реЗ рдЬрд╛рдПрдЧрд╛, рд╕рдВрдкрддреНрддрд┐ рдкрде member рдирд┐рдХрд╛рд▓реЗрдВ, рдФрд░ рдЗрд╕реЗ рд╕рдВрдХрд▓рд┐рдд рд╕реНрдЯреНрд░рд┐рдВрдЧ "member" рд╕рдВрдХрд▓рди рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВ рд╕рдордпред рдПрдХ рдХрдо рд╡рд┐рд╢реЗрд╖ рдкреВрд░рдХ @typeReferenceOf рдкреВрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ "typeof instance.member" рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдЧрд╛ред

рддреЛ рдЕрдм:

getProperty<C, typeof instance.subObject>(instance);

рдЗрд╕рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдВрдЧреЗ:

getProperty<C, typeof instance.subObject>(instance, "subObject");

рдФрд░ getPath рд▓рд┐рдП рд╕рдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:

getPath<C, typeof instance.a.b.c>(instance);

рдЗрд╕рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдВрдЧреЗ:

getPath<C, typeof instance.a.b.c>(instance, "a.b.c");

рдЪреВрдБрдХрд┐ @typeReferencePathOf(P) рдХреЗрд╡рд▓ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рддрд░реНрдХ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

getPath<C, SomeTypeWhichIsNotAPath>(instance, "member.someSubMember.AnotherSubmember.data");

рдпрджрд┐ рджреВрд╕рд░реЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ @typeReferencePathOf() рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ undefined рдпрд╛ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ "" рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рдПрдХ рдкреНрд░рдХрд╛рд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЖрдВрддрд░рд┐рдХ рдорд╛рд░реНрдЧ рдирд╣реАрдВ рдерд╛, рддреЛ рдпрд╣ "" рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдЧрд╛ред

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд▓рд╛рдн:

  • рдЙрдЪреНрдЪ-рдкреНрд░рдХрд╛рд░ рдХреА рдЬреЗрдирд░рд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
  • рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╢рд╛рдмреНрджрд┐рдХ рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
  • рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдЬреЗрдиреЗрд░рд┐рдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
  • typeof рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╕рдордп рд╕реНрд╡рддрдГ рдкреВрд░реНрдгрддрд╛ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░ рд╕рдВрдХрд▓рди-рд╕рдордп рдкрд░ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╕реЗ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрдЬрд╛рдп рдЗрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореМрдЬреВрджрд╛ рдЬрд╛рдБрдЪ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
  • рдЬреЗрдиреЗрд░рд┐рдХ рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рднреА рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
  • typeon рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ (рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдорд░реНрдерди рдХрд░ рд╕рдХрддрд╛ рд╣реИ)ред
  • рдЕрдиреНрдп рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

+1

рдЕрдЪреНрдЫрд╛ рд▓рдЧрд╛! рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрдбрд╝рд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЪрд░реНрдЪрд╛ рдХреЛ рдкрд╛рдпрд╛, рддреЛ рдЖрдЗрдП рдпрд╣рд╛рдВ рдЪрд░реНрдЪрд╛ рдХрд░рддреЗ рд╣реИрдВред

рдпрд╣рд╛рдБ рдореЗрд░реЗ рдЧреИрд░ рдкреНрд░рд╕реНрддреБрдд рдореБрджреНрджреЗ рд╕реЗ рдПрдХ рдЙрджреНрдзрд░рдг рд╣реИ:

рдкреНрд░рд╢реНрди : .d.ts рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреИрд╕реЗ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд╣рд╛рдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИ?

function mapValues(obj, fn) {
      return Object.keys(obj)
          .map(key => ({key, value: fn(obj[key], key)}))
          .reduce((res, {key, value}) => (res[key] = value, res), {})
}

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди (рдереЛрдбрд╝реЗ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде) рд▓рдЧрднрдЧ рд╣рд░ рд╕рд╛рдорд╛рдиреНрдп "рдмрд░реНрддрдиреЛрдВ" рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЬрдВрдЧрд▓реА рдореЗрдВ mapValues рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рд╣реИрдВ:

рдПред _Object-as-a -_ -_ _ _ рдЬрд╣рд╛рдВ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдЧрддрд┐рд╢реАрд▓ рд╣реИрдВ, рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рд╣реИ, рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╕рд╛рдорд╛рдиреНрдп рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИ рдореЛрдиреЛрдореЛрд░реНрдлрд┐рдХ (рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛)

var obj = {'a': 1, 'b': 2, 'c': 3};
var res = mapValues(x, val => val * 5); // {a: 5, b: 10, c: 15}
console.log(res['a']) // 5

рдмреА _Object-as-a-_ -Record _ рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЕрдкрдирд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЬрдмрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдкреИрд░рд╛рдореАрдЯреНрд░рд┐рдХ рдкреЙрд▓реАрдореЙрд░реНрдлрд┐рдХ рд╣реИ (рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рджреНрд╡рд╛рд░рд╛)

var obj = {a: 123, b: "Hello", c: true};
var res = mapValues(p, val => [val]); // {a: [123], b: ["Hello"], c: [true]}
console.log(res.a[0].toFixed(2)) // "123.00"

рд╡рд░реНрддрдорд╛рди рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде mapValues рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЙрдкрд▓рдмреНрдз рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди рд╣реИ:

declare function mapValues<T1, T2>(
    obj: {[key: string]: T1},
    fn: (arg: T1, key: string) => T2
): {[key: string]: T2};

рдпрд╣ рджреЗрдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ _Object-as-a -_ -_ _ _ _ рдЗрдВрд╕реНрдкреЗрдХреНрд╢рди рдХрд╛ рдХреБрдЫ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ 1 рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ _Object-as-a-_ _Record _ рдЗрд░рд╛рджрд╛ рдерд╛ред

рдкреНрд░рдХрд╛рд░ {p1: T1, p2: T2, ...pn: Tn} {[key: string]: T1 | T2 | ... | Tn } рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реБрдП рдФрд░ рд░рд┐рдХреЙрд░реНрдб рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдкреНрд░рднрд╛рд╡реА рдврдВрдЧ рд╕реЗ рдЦрд╛рд░рд┐рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

  • рд╕рд╣реА рдФрд░ рдЕрдкреЗрдХреНрд╖рд┐рдд 2 рдареАрдХ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП console.log(res.a[0].toFixed(2)) рд╕рдВрдХрд▓рдХ рджреНрд╡рд╛рд░рд╛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛;
  • рд╕реНрд╡реАрдХреГрдд console.log((<number>res['a'][0]).toFixed(2)) рдореЗрдВ рджреЛ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдФрд░ рддреНрд░реБрдЯрд┐-рдкреНрд░рд╡рдг рд╕реНрдерд╛рди рд╣реИрдВ: рдЯрд╛рдЗрдк-рдХрд╛рд╕реНрдЯ рдФрд░ рдордирдорд╛рдирд╛ рд╕рдВрдкрддреНрддрд┐ рдирд╛рдоред

1, 2 - рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд▓рд┐рдП рдЬреЛ ES рд╕реЗ TS рдХреЗ рд▓рд┐рдП рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рддрд╛ рд╣реИ


рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╛рд╡рд┐рдд рдХрджрдо (рдФрд░ рджреВрд╕рд░реЛрдВ рдХреЛ рднреА рд╣рд▓ рдХрд░реЗрдВ)

1. рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдорджрдж рд╕реЗ рд╡реИрд░рд┐рдХрд╛рдб рд░рд┐рдХреЙрд░реНрдб рдХрд╛ рдкрд░рд┐рдЪрдп

type Numbers<p extends string> =  { ...p: number };
type NumbersOpt<p extends string> = {...p?: number };
type ABC = "a" | "b" | "c";
type abc = Numbers<ABC> // abc =  {a: number, b: number, c: number} 
type abcOpt = NumbersOpt<ABC> // abcOpt =  {a?: number, b?:number, c?: number}

function toFixedAll<p extends string>(obj: {...p: number}, precision):{...p: string}  {
      var result: {...p: string} = {} as any;
      Object.keys(obj).forEach((p:p) => {
           result[p] = obj[p].toFixed(precision);
      });
      return result;
}

var test = toFixedAll({x:5, y:7}, 3); // { x: "5.00", y: "6.00" },  p inferred as "x"|"y"
console.log(test.y.length) // 4   test.y: string
2. рдФрдкрдЪрд╛рд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ 'рд╕реНрдЯреНрд░рд┐рдВрдЧ' рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╡рд╢ рдЕрдиреНрдп рдФрдкрдЪрд╛рд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ

рдЙрджрд╛рд╣рд░рдг:


declare function mapValues<p extends string, T1[p], T2[p]>(
     obj:{...p: T1[p]}, fn:(arg: T1[p]) => T2[p]
): {...p: T2[p]};
3. рдФрдкрдЪрд╛рд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╡рд┐рдирд╛рд╢ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ

рдЙрджрд╛рд╣рд░рдг:

class C<Array<T>> {
     x: T;
}   

var v1: C<string[]>;   // v1.x: string

рд╕рднреА рддреАрди рдЪрд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╣рдо рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

declare module Backbone {

  class Model<{...p: T[p]}> {
    get(prop: p): T[p];
    set(prop: p, value: T[p]): void;
  }
}

declare module ImmutableJS {
  class Map<{...p: T[p]}> {
    get(prop: p): T[p];
    set(prop: p, value: T[p]): this;
  }
}

declare function pluck<p extends string, T[p]>(
    arr: Array<{...p:T[p]}>, prop: p
): Array<T[p]> 

рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╕рд┐рдВрдЯреИрдХреНрд╕ @fdecampredon рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдХреНрд░рд┐рдпрд╛ рд╣реИ
рд▓реЗрдХрд┐рди рдореИрдВ рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдХрд┐ рдореВрд▓ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд╕рд╛рде mapValues рдпрд╛ combineReducers рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдХреИрд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдПред

function combineReducers(reducers) {
  return (state, action) => mapValues(reducers, (reducer, key) => reducer(state[key], action))
}

рдореЗрд░реЗ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд╕рд╛рде рдЗрд╕рдХреА рдШреЛрд╖рдгрд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:

declare function combineReducers<p extends string, S[p]>(
    reducers: { ...p: (state: S[p], action: Action) => S[p] }
): (state: { ...p: S[p] }, action: Action) => { ...p: S[p] };

рдХреНрдпрд╛ рдпрд╣ рдореВрд▓ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд╕рд╛рде рд╕реНрдкрд╖реНрдЯ рд╣реИ?

@spion , @fdecampredon ?

@Artazor рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рд╕реБрдзрд╛рд░ рд╣реИред рдЕрдм рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рдореЗрд░реЗ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдирд╛ рдХрд╛рдлреА рдЕрдЪреНрдЫрд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ:

user.id рдФрд░ user.name рдорд╛рдирдХрд░ user.id number рдФрд░ string рдЕрдиреБрд╕рд╛рд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реНрддрдВрдн рдкреНрд░рдХрд╛рд░ рд╣реИрдВ рдпрд╛рдиреА Column<number> рдФрд░ Column<string>

рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкреНрд░рдХрд╛рд░ рд▓рд┐рдЦреЗрдВ select рдЬреЛ рд▓реЗрддрд╛ рд╣реИ:

select({id: user.id, name: user.name})

рдФрд░ Query<{id: number; name: string}>

select<T>({...p: Column<T[p]>}):Query<T>

рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдЬрд╛рдБрдЪ рдХреА рдФрд░ рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЯрд╛рдЗрдк T рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред рдХреНрдпрд╛ рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЛ рд╡рд┐рдирд╛рд╢рдХрд╛рд░реА рд░реВрдк рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА? рдЕрд░реНрдерд╛рдд

select<T>({...p: Column<T[p]>}):Query<{...p:T[p]}>

@Artazor рдкреВрдЫрдирд╛ рднреВрд▓ рдЧрдпрд╛, рдХреНрдпрд╛ p extends string рдкреИрд░рд╛рдореАрдЯрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИ?

рдХреНрдпрд╛ рдРрд╕рд╛ рдХреБрдЫ рдХрд░рдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрдЧрд╛?

select<T[p]>({...p: Column<T[p]>}):Query<{...p:T[p]}>

рдпрд╛рдиреА рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП T [p] {...p:Column<T[p]>}

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдПрдХ рдФрд░ рд╕рд╡рд╛рд▓, рдпрд╣ рдХреИрд╕реЗ рд╕рд╣реА рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ?

@spion рдореБрдЭреЗ рдЖрдкрдХреА рдмрд╛рдд рд╕рдордЭ рдореЗрдВ рдЖ рдЧрдИ рд╣реИ - рдЖрдкрдиреЗ T[p] рдореБрдЭреЗ рдЧрд▓рдд рд╕рдордЭрд╛ рд╣реИ (рд▓реЗрдХрд┐рди рдпрд╣ рдореЗрд░реА рдЧрд▓рддреА рд╣реИ), рдореЗрд░рд╛ рдорддрд▓рдм рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдЪреАрдЬ рд╕реЗ рд╣реИ, рдФрд░ рдЖрдк рдЙрд╕ p extends string рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред

рдЪрд▓реЛ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЪрд╛рд░ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ: List , Tuple , Dictionary рдФрд░ Record ред рд╣рдо рдЙрдиреНрд╣реЗрдВ _conceptual data structure_ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░реЗрдВрдЧреЗ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде рдЙрдирдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВрдЧреЗ:

рд╡реИрдЪрд╛рд░рд┐рдХ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВрджреНрд╡рд╛рд░рд╛ рдкрд╣реБрдБрдЪ
рдПред рдкрдж
(рд╕рдВрдЦреНрдпрд╛)
рдмреА рдЪрд╛рднреА
(рд╕реНрдЯреНрд░рд┐рдВрдЧ)
рдХреА рдЧрд┐рдирддреА
рдЖрдЗрдЯрдо
1. рдЪрд░
(рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рднреВрдорд┐рдХрд╛)
рд╕реВрдЪреАрд╢рдмреНрджрдХреЛрд╢
2. рдирд┐рдпрдд
(рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдЕрдкрдиреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ)
рдЯрдкрд▓рдЕрднрд┐рд▓реЗрдЦ

рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ, рдЗрди рдЪрд╛рд░ рдорд╛рдорд▓реЛрдВ рдХреЛ рджреЛ рднрдВрдбрд╛рд░рдг рд░реВрдкреЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: a Array - a1 рдФрд░ a2 рдХреЗ рд▓рд┐рдП , рдФрд░ Object - b1 рдФрд░ b2 рдХреЗ рд▓рд┐рдП ред

_Note 1 _ред рдИрдорд╛рдирджрд╛рд░ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдХрд╣рдирд╛ рд╕рд╣реА рдирд╣реАрдВ рд╣реИ рдХрд┐ Tuple Array рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХреЗрд╡рд▓ "рд╕рддреНрдп" рдЯрдкрд▓ рдкреНрд░рдХрд╛рд░ arguments рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬреЛ Array ред рдлрд┐рд░ рднреА, рд╡реЗ рдЕрдзрд┐рдХ рдпрд╛ рдХрдо рд╡рд┐рдирд┐рдореЗрдп рд╣реИрдВ, рдЦрд╛рд╕рдХрд░ рд╡рд┐рдирд╛рд╢рдХрд╛рд░реА рдФрд░ Function.prototype.apply рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЬреЛ рдореЗрдЯрд╛-рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рджрд░рд╡рд╛рдЬрд╛ рдЦреЛрд▓рддрд╛ рд╣реИред рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рднреА Tuples рдореЙрдбрд▓рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП Arrays рдХрд╛ рд▓рд╛рдн рдЙрдард╛рддреА рд╣реИред

_Note 2 _ред рдЬрдмрдХрд┐ рдИрдПрд╕ 6 Map рд░реВрдк рдореЗрдВ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╢рдмреНрджрдХреЛрд╢ рдХреА рдкреВрд░реНрдг рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдмрд╛рдж рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдмреНрд░реЗрдВрдбрди рдИрдЪ рдХрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ Record рдФрд░ рдПрдХ рд╕реАрдорд┐рдд Dictionary (рд╕рд╛рде рджреЗрдиреЗ рдХрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдирд┐рд░реНрдгрдп) рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреБрдВрдЬреА рдХреЗрд╡рд▓) Object (рдЬрд╣рд╛рдВ obj.prop obj["prop"] рдмрд░рд╛рдмрд░ рд╣реИ) рдХреЗ рдПрдХ рд╣реА рд╣реБрдб рдХреЗ рддрд╣рдд рдкреВрд░реА рднрд╛рд╖рд╛ рдХрд╛ рд╕рдмрд╕реЗ рд╡рд┐рд╡рд╛рджрд╛рд╕реНрдкрдж рддрддреНрд╡ рдмрди рдЧрдпрд╛ (рдореЗрд░реА рд░рд╛рдп рдореЗрдВ)ред
рдпрд╣ рд╢рд╛рдк рдФрд░ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╢рдмреНрджрд╛рд░реНрде рджреЛрдиреЛрдВ рдХрд╛ рдЖрд╢реАрд░реНрд╡рд╛рдж рд╣реИред рдпрд╣ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЛ рддреБрдЪреНрдЫ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░реЛрдВ рдХреЛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ _programming_ рдФрд░ _meta-programming_ рдХреЗ рд╕реНрддрд░ рдХреЗ рдмреАрдЪ рд▓рдЧрднрдЧ рд╢реВрдиреНрдп рдорд╛рдирд╕рд┐рдХ рд▓рд╛рдЧрдд (рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдмрд┐рдирд╛ рд╕реВрдЪрдирд╛ рдХреЗ!) рдХреЗ рдмреАрдЪ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдлрд▓рддрд╛ рдХрд╛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред

рдЕрдм рдпрд╣ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдЕрдЬреАрдм рд╢рдмреНрджрд╛рд░реНрде рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд░ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдЬрдм рд╣рдо рд╕реЛрдЪрддреЗ рд╣реИрдВ рдХрд┐ _programming_ рд╕реНрддрд░ рдкрд░ рд╕рдм рдареАрдХ рд╣реИ:

рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╕реНрддрд░ рдкрд░ рдкреНрд░рдХрд╛рд░рджреНрд╡рд╛рд░рд╛ рдкрд╣реБрдБрдЪ
рдПред рдкрдж
(рд╕рдВрдЦреНрдпрд╛)
рдмреА рдЪрд╛рднреА
(рд╕реНрдЯреНрд░рд┐рдВрдЧ)
рдХреА рдЧрд┐рдирддреА
рдЖрдЗрдЯрдо
1. рдЪрд░
(рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рднреВрдорд┐рдХрд╛)
рдЯреА []{[рдХреБрдВрдЬреА: рд╕реНрдЯреНрд░рд┐рдВрдЧ]: рдЯреА}
2. рдирд┐рдпрдд
(рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдЕрдкрдиреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ)
[T1, T2, ...]{рдХреА рез: рдЯреА рез, рдХреА реи: рдЯреА реи, ...}

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЬрдм рд╣рдо _meta-programming_ рд╕реНрддрд░ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ _programming_ рд╕реНрддрд░ рдкрд░ рддрдп рдХреА рдЧрдИ рдЪреАрдЬреЗрдВ рдЕрдЪрд╛рдирдХ рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рд╣реЛ рдЬрд╛рддреА рд╣реИрдВ! рдФрд░ рдпрд╣рд╛рдБ рд╣рдо рдЕрдЪрд╛рдирдХ рдЯреНрдпреВрдкрд▓реНрд╕ рдФрд░ рдлрдВрдХреНрд╢рди рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдХреЗ рдмреАрдЪ рд╕рдВрдмрдВрдзреЛрдВ рдХреЛ рдкрд╣рдЪрд╛рдирддреЗ рд╣реИрдВ рдФрд░ # 5453 (рд╡реИрд░рд┐рдПрдбрд┐рдХ рдХрд┐рдВрдбреНрд╕) рдЬреИрд╕реА рдЪреАрдЬреЛрдВ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрдЯреНрд░реЛрдкреЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдЬрд░реВрд░рддреЛрдВ рдХреЗ рдХреЗрд╡рд▓ рдЫреЛрдЯреЗ (рд▓реЗрдХрд┐рди рдХрд╛рдлреА рдорд╣рддреНрд╡рдкреВрд░реНрдг) рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдХрд╡рд░ рдХрд░рддреЗ рд╣реИрдВ - рдПрдХ рдФрдкрдЪрд╛рд░рд┐рдХ рдХреЛ рдирд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рджреЗрдХрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░реЛрдВ рдХрд╛ рд╕рдВрдпреЛрдЬрдиред рдмрд╛рдХреА рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░:

     function f<T>(a: number, ...args:T) { ... }

    f<[string,boolean]>(1, "A", true);

рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрджрд┐ # 6018 рднреА рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рддреЛ рдлрдВрдХреНрд╢рди рдХреНрд▓рд╛рд╕ рдЬреИрд╕рд╛ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ

declare class Function<This, TArgs, TRes> {
        This::(...args: TArgs): TRes;
        call(self: This, ...args: TArgs): TRes;
        apply(self: This, args: TArgs): TRes;
        // bind needs also formal pattern matching:
        bind<[...TPartial, ...TCurried] = TArgs>(
           self: This, ...args: TPartial): Function<{}, TCurried, TRes> 
}

рдпрд╣ рдорд╣рд╛рди рд╣реИ рд▓реЗрдХрд┐рди рд╡реИрд╕реЗ рднреА рдЕрдзреВрд░рд╛ рд╣реИред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рдЕрд╕рд╛рдЗрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:

function extractAndWrapAll(...args) {
     return args.map(x => [x]);
}

// wrapAll(1,"A",true) === [[1],["A"],[true]]

рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╣рдо рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдХреБрдЫ рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдХреА рдЬрд░реВрд░рдд рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдВрдХрд▓рди-рд╕рдордп рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдирд╛ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИ рдЬреЛ рдХрд┐ рдкреНрд░рдХрд╛рд░ (рдлреЗрд╕рдмреБрдХ рдХреЗ рдкреНрд░рд╡рд╛рд╣ рдореЗрдВ) рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдпрд╣ рддрдм рд╣реА рд╕рдВрднрд╡ рд╣реЛрдЧрд╛, рдЬрдм (рдФрд░ рдЕрдЧрд░) рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдЕрдЧрд▓реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд╕рд╛рдордиреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрджреНрдпрддрди рдХреЛ рддреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЬреЛрдЦрд┐рдо рдХреЗ рдмрд┐рдирд╛ рдЗрд╕реЗ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╕реНрдерд┐рд░ рд╣реЛрдЧрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдкреВрд░реНрдг рдореЗрдЯрд╛-рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╕рдорд░реНрдерди рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреБрдЫ рдХрдо рдХрдЯреНрдЯрд░рдкрдВрдереА рдЪрд╛рд╣рд┐рдП рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдкреНрд░рджрд░реНрд╢рди рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ _object рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░_ рдХреА рдзрд╛рд░рдгрд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдБред рдореЛрдЯреЗ рддреМрд░ рдкрд░ рдпрд╣ рдпрд╛ рддреЛ рд╣реИ

  1. рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рдВрдкрддреНрддрд┐ рдирд╛рдореЛрдВ рдХрд╛ рд╕реЗрдЯ, рдпрд╛
  2. рд╢рдмреНрджрдХреЛрд╢ рдХреА рдХреБрдВрдЬреА рдХрд╛ рд╕реЗрдЯ, рдпрд╛
  3. рдХрд┐рд╕реА рд╕рд░рдгреА рдХреЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рд╕реЗрдЯ
  4. рдЯрдкрд▓ рдХреЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдкрджреЛрдВ рдХрд╛ рд╕реЗрдЯред

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдкреВрд░реНрдгрд╛рдВрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╕реНрдЯреНрд░рд┐рдВрдЧ рдпрд╛ рдЯреНрдпреВрдкрд▓ рдЬреИрд╕реЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░реЛрдВ рдХреЛ рджрд░реНрд╢рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рд╣реЛрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

type ZeroToFive = 0 | 1 | 2 | 3 | 4 | 5;
// or
type ZeroToFive = 0 .. 5;   // ZeroToFive extends number (!)

рдкреВрд░реНрдгрд╛рдВрдХ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреЗ рдирд┐рдпрдо рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВ;

рддрдм рд╣рдо рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдПрдмреНрд╕реНрдЯреНрд░рдХреНрд╢рди рд╕рд┐рдВрдЯреИрдХреНрд╕ рдкреЗрд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рд░реЗрд╕реНрдЯ / рд╕реНрдкреНрд░реЗрдб рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реЗ рдмрд┐рд▓реНрдХреБрд▓ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ:

{...Props: T }

рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде: рдпрд╣рд╛рдВ Props рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд╣реИ рдЬреЛ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХреНрд╡рд╛рдВрдЯрд┐рдлрд╛рдпрд░ рдХреЗ рддрд╣рдд рдмрд╛рдзреНрдп рд╣реИ:

<Props extends string> {...Props: T }  // every property has type T
<Index extends number> {...Index: T }  // every item has type T  
// the same as T[]

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЗрд╕реЗ рдЯрд╛рдЗрдк рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╕реНрдХреЛрдк рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рд╕реНрдХреЛрдк рдХреЗ рдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╣реАрдВ рднреА рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рджреЛрд╣рд░рд╛ рд╣реИ: рдЬрдм рдЖрд░рд╛рдо / рдкреНрд░рд╕рд╛рд░ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдпрд╣ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдкрд░ рдЕрдореВрд░реНрддрддрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ рдЬрдм рдЗрд╕реЗ рдПрдХ рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдпрд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдпрд╛ рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдПрдХ рдЙрдкрдкреНрд░рдХрд╛рд░) рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред

declare class Object {
      static keys<p extends string, q extends p>(object{...q: {}}): p[];
}

рдФрд░ рдпрд╣рд╛рдБ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдкрд░рд┐рд╖реНрдХреГрдд рднрд╛рдЧ рд╣реИ: _Key рдЖрд╢реНрд░рд┐рдд рдкреНрд░рдХрд╛рд░_

рд╣рдо рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВ: T for Prop (рдореИрдВ рдЗрд╕ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ T [Prop] рдХреЗ рдмрдЬрд╛рдп рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдЖрдкрдХреЛ рднреНрд░рдорд┐рдд рдХрд░рддрд╛ рд╣реИ) рдЬрд╣рд╛рдВ Prop рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдЪрд░ рдХрд╛ рдирд╛рдо рд╣реИ рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЛ рдЕрдореВрд░реНрдд рд░рдЦрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП <Prop extends string, T for Prop> рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рдкреНрд░рдХрд╛рд░ рд╢рд╛рдмреНрджрд┐рдХ рджрд╛рдпрд░реЗ рдореЗрдВ рджреЛ рдФрдкрдЪрд╛рд░рд┐рдХ рдкреНрд░рдХрд╛рд░, Prop рдФрд░ T рдЬрд╣рд╛рдВ рдпрд╣ рдЬреНрдЮрд╛рдд рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╢реЗрд╖ рдореВрд▓реНрдп рдХреЗ рд▓рд┐рдП p рдХреЗ Prop рд╡рд╣рд╛рдБ рдпрд╣ T рдЦреБрдж рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛ред

рд╣рдо рдпрд╣ рдирд╣реАрдВ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдХрд╣реАрдВ рди рдХрд╣реАрдВ рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рд╣реИ рдЬрд┐рд╕рдХреА рд╕рдВрдкрддреНрддрд┐ Props рдФрд░ рдЙрдирдХреЗ рдкреНрд░рдХрд╛рд░ T ! рд╣рдо рдХреЗрд╡рд▓ рджреЛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВред рдЯрд╛рдЗрдк рдЯреА рдХреЛ Props рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╣рд╕рдВрдмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╕рдм!

рдпрд╣ рд╣рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреА рдЪреАрдЬреЗрдВ рд▓рд┐рдЦрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рджреЗрддрд╛ рд╣реИ

function unwrap<P extends string, T for P>(obj:{...P: Maybe<T>}): Maybe<{...P: T}> {
  ...
}

unwrap({a:{value:1}, b:{value:"A"}, c:{value: true}}) === { a: 1, b: "A", c: true }
// here actual parameters will be inferred as 
unwrap<"a"|"b"|"c", {a: number, b: string, c: boolean}>

рд╣рд╛рд▓рд╛рдБрдХрд┐ рджреВрд╕рд░реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдПрдХ рд╡рд╕реНрддреБ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЗ рдЕрдореВрд░реНрдд рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдкрд░рд┐рдкреНрд░реЗрдХреНрд╖реНрдп рдореЗрдВ T for P рдХрд╛ рдЙрдкрдпреЛрдЧ tuples рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдЕрдореВрд░реНрдд рджреГрд╢реНрдпреЛрдВ рдХреЛ рджрд░реНрд╢рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм P рд╕рдВрдЦреНрдпрд╛ ( @JsonFreeman ?) рдХрд╛ рдЙрдк-рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИ?

рдЬрдм T рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╣реАрдВ рди рдХрд╣реАрдВ {...P: .... T .... } рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдпрд╣ рдЙрд╕ рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдмрд┐рд▓реНрдХреБрд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред

рдпрд╣ рдореЗрд░рд╛ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ рд╣реИред
рдХрд┐рд╕реА рднреА рдкреНрд░рд╢реНрди, рд╡рд┐рдЪрд╛рд░, рдЖрд▓реЛрдЪрдирд╛ рдХрд╛ рдмреЗрд╕рдмреНрд░реА рд╕реЗ рдЗрдВрддрдЬрд╛рд░ -)

рдареАрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП extends string рдХреЛ рдПрдХ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рд░рдгрд┐рдпреЛрдВ (рдФрд░ рд╡реИрд░рд╛рдбрд┐рдХ рддрд░реНрдХ) рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░реЗ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рд░рд╛рдВрдХ (рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ) рд╣реИред рдорд┐рдард╛рдИ!

рд╣рдо рдпрд╣ рдирд╣реАрдВ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдХрд╣реАрдВ рди рдХрд╣реАрдВ рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЧреБрдг рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдкреНрд░рдХрд╛рд░ T рд╣реИрдВ! рд╣рдо рдХреЗрд╡рд▓ рджреЛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВред рдЯрд╛рдЗрдк рдЯреА рдХреЛ Props рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╣рд╕рдВрдмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╕рдм!

рдореЗрд░рд╛ рдпрд╣ рдорддрд▓рдм рдирд╣реАрдВ рдерд╛, рдореЗрд░рд╛ рдорддрд▓рдм рдпрд╣ рдерд╛ рдХрд┐ рдЙрдирдХреЗ рдкреНрд░рдХрд╛рд░ рдЯреА [рдкреА] рд╣реИрдВ, рдкреА рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ред рдЕрдЧрд░ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЕрдВрддрд░реНрдЬреНрдЮрд╛рди рд╣реИ, рддреЛ рдореИрдВ рдпрд╣реА рд░рдЦреВрдВрдЧрд╛ред

рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЛ рдереЛрдбрд╝рд╛ рдФрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдЪрд╛рд░ рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ рд▓рдЧрддрд╛ рд╣реИред

рдХреНрдпрд╛ рд╡реИрд░рд┐рдПрдмрд▓ рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП unwrap рд▓рд┐рдЦрдирд╛ рд╕рдВрднрд╡ рд╣реИ?

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ, рдореБрдЭреЗ рд╕рд┐рд░реНрдл рдпрд╣ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ рд╡реИрд░рд╛рдбрд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрдкрдХреЗ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИред

рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░,
рдореИрдВ рд╣реИрд░рд╛рди рд╣реВрдБ рдХрд┐ рдореИрдВ рдЕрдкрдиреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдХреИрд╕реЗ рд╣рд▓ рдХрд░реВрдВ рдФрд░ рдЗрд╕ рдЪрд░реНрдЪрд╛ рдХреЛ рдкрд╛рдпрд╛ред
рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ:
рдореЗрд░реЗ рдкрд╛рд╕ RpcManager.call(command:Command):Promise<T> рд╡рд┐рдзрд┐ рд╣реИ, рдФрд░ рдЙрдкрдпреЛрдЧ рдРрд╕рд╛ рд╣реЛрдЧрд╛:

RpcManager.call(new GetBalance(123)).then((result) => {
 // here I want that result would have a type.
});

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдорд╛рдзрд╛рди рдХреА рддрд░рд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:

interface Command<T> {
    responseType:T;
}

class GetBalance implements Command<number> {
    responseType: number; // somehow this should be avoided. maybe Command should be abstract class.
    constructor(userId:number) {}
}

class RpcManager {
    static call(command:Command):Promise<typeof command.responseType> {
    }
}

or:

class RpcManager {
    static call<T>(command:Command<T>):Promise<T> {
    }
}

рдЗрд╕ рдкрд░ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░?

@ antanas-arvasevicius рдЙрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЕрдВрддрд┐рдо рдХреЛрдб рдмреНрд▓реЙрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдПред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рдкреНрд░рд╢реНрди рд╣реИ; рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдпрд╛ рдпрджрд┐ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдПрдХ рдХрдВрдкрд╛рдЗрд▓рд░ рдмрдЧ рдорд┐рд▓ рдЧрдпрд╛ рд╣реИ рддреЛ рдПрдХ рд╕рдорд╕реНрдпрд╛ рджрд░реНрдЬ рдХрд░реЗрдВред

рд╣рд╛рдп, рд░рдпрд╛рди, рдЖрдкрдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рдореИрдВрдиреЗ рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ рдХрд┐ рдХреЛрдб рдХреЗ рдЕрдВрддрд┐рдо рдмреНрд▓реЙрдХ рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рддреНрд╡рд░рд┐рдд рдбреЗрдореЛ:

interface Command<T> { }
class MyCommand implements Command<{status:string}> { }
class RPC { static call<T>(command:Command<T>):T { return; } }

let response = RPC.call(new MyCommand());
console.log(response.status);

//output: error TS2339: Property 'status' does not exist on type '{}'.
//tested with: Version 1.9.0-dev.20160222

рдЦреЗрдж рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрд╛ рдХрд┐ рдпрд╣ рдЗрд╕ рдореБрджреНрджреЗ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ :)
рдХреНрдпрд╛ рдореБрдЭреЗ рдЗрд╕ рд╡рд┐рд╖рдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рдЦреЛрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП?

рдПрдХ рдЧреИрд░-рд╕рд╛рдорд╛рдиреНрдп рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ; рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░ рдЖрдкрдХреЛ _never_ рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рдШреЛрд╖рдгрд╛рдУрдВ рдореЗрдВ рдЕрдкреНрд░рдпреБрдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдЕрд░реНрдерд╣реАрди рд╣реИрдВред рдпрджрд┐ рдЖрдк T рдЙрдкрднреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕рдм рдХреБрдЫ рдмрд╕ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

interface Command<T> { foo: T }
class MyCommand implements Command<{status:string}> { foo: { status: string; } }
class RPC { static call<T>(command:Command<T>):T { return; } }

let response = RPC.call(new MyCommand());
console.log(response.status);

рдпрд╣ рд╕рд┐рд░реНрдл рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реИ! рдзрдиреНрдпрд╡рд╛рдж!
рдореИрдВрдиреЗ рдирд╣реАрдВ рд╕реЛрдЪрд╛ рд╣реИ рдХрд┐ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдВрджрд░ рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░
рдЯреАрдПрд╕ рдЙрд╕реЗ рдирд┐рдХрд╛рд▓реЗрдЧрд╛ред
рдлрд░рд╡рд░реА 22, 2016 11:56 рдЕрдкрд░рд╛рд╣реНрди, "рд░рдпрд╛рди рдХреИрд╡рд╛рдиреБрдШ" рд╕реВрдЪрдирд╛рдПрдБ @ithub.com рдиреЗ рд▓рд┐рдЦрд╛:

рдПрдХ рдЧреИрд░-рд╕рд╛рдорд╛рдиреНрдп рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ; рдореЗрдВ
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░ рдЖрдкрдХреЛ _never_ рдХреЗ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЕрдкреНрд░рдпреБрдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП
рдШреЛрд╖рдгрд╛рдПрдВ рдирд┐рд░рд░реНрдердХ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЯреА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдмрд╕ рд╕рдм рдХреБрдЫ
рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрдорд╛рдВрдб{foo: T} рд╡рд░реНрдЧ MyCommand рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдХрдорд╛рдВрдб <{status: string}> {foo: {status: string; }} рд╡рд░реНрдЧ RPC {рд╕реНрдерд┐рд░ рдХреЙрд▓(рдХрдорд╛рдВрдб: рдХрдорд╛рдВрдб): рдЯреА {рд╡рд╛рдкрд╕реА; }}
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрдВ = RPC.call (рдирдпрд╛ MyCommand ());
рдХрдВрд╕реЛрд▓.рд▓реЙрдЧ (рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛.рд╕реНрдЯреИрдЯрд╕);

-
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рдЙрддреНрддрд░ рд╕реАрдзреЗ рджреЗрдВ рдпрд╛ рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/Microsoft/TypeScript/issues/1295#issuecomment -187404245
ред

рдпрджрд┐ рдЖрдк RPC рд╢реИрд▓реА API рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЖрдк рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ @ antanas-arvasevicius: https://github.com/alm-tools/alm/blob/master/docs/contributing.nYNC.md : рдЧреБрд▓рд╛рдм

рдКрдкрд░ рджрд┐рдП рдЧрдП рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреНрд░рддреАрдд рд╣реЛрддреЗ рд╣реИрдВ:

  • рдХрд╛рдлреА рдЬрдЯрд┐рд▓;
  • рдХреЛрдб рдореЗрдВ рддрд╛рд░ рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдирд╣реАрдВ рд╣реИред string "рд╕рднреА рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рдвреВрдВрдвреЗрдВ" -able рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ рди рд╣реА рд░реАрдкреЗрдХреНрдЯреЗрдмрд▓ (рдЬреИрд╕реЗ рдирд╛рдо)ред
  • рдХреБрдЫ рдХреЗрд╡рд▓ "рдкреНрд░рдердо рд╕реНрддрд░" рдЧреБрдгреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдирд╣реАрдВ (рдЬреЛ рдХреБрдЫ рд░реВрдкрд░реЗрдЦрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ)ред

рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рдЬреЛ рд╕реА # рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдкреЗрдбрд╝реЛрдВ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИред рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рдореЛрдЯрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реЛрдЪрд╛-рд╕рдордЭрд╛ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ! рд╕рд┐рдВрдЯреЗрдХреНрд╕ рднрдпрд╛рдирдХ рд╣реИред рдореИрдВ рд╕рд┐рд░реНрдл рдпрд╣ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдХрд┐рд╕реА рдХреЛ рдкреНрд░реЗрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рджрд░реНрд╢рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд╛рд░ рд╣реИрдВред
рдЪрд▓реЛ рдЗрд╕реЗ type Expr<T, U> = string ред
рдЬрд╣рд╛рдБ T рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╡рд╕реНрддреБ рдкреНрд░рдХрд╛рд░ рд╣реИ рдФрд░ U рдкрд░рд┐рдгрд╛рдо рдкреНрд░рдХрд╛рд░ рд╣реИред

рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ Expr<T,U> рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗрддрд╛ рд╣реИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ T рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдЙрд╕ рдкрд░ рдПрдХ рд╕рджрд╕реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: person => person.address.city ред
рдЬрдм рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдкреВрд░реЗ рд▓реИрдореНрдмреНрдбрд╛ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд░ рдЬреЛ рднреА рдкрд╣реБрдВрдЪ рд╣реЛрддреА рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ: "address.city" ред

рдЖрдк рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд╕рд╛рджреЗ рддрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ Expr<any, any> рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛рдПрдЧрд╛ред

рдпрд╣ рд╡рд┐рд╢реЗрд╖ Expr рднрд╛рд╖рд╛ рдореЗрдВ

function pluck<T, U>(array: T[], prop: Expr<T, U>): U[];

let numbers = pluck([{x: 1}, {x: 2}], p => p.x);  // number[]
// compiles to:
// let numbers = pluck([..], "x");

рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ C # рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕реАрдорд┐рдд рд░реВрдк рд╣реИред
рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд░рд┐рд╖реНрдХреГрдд рдФрд░ рдХрд╣реАрдВ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

@fdecampredon @RyanCavanaugh

_ ( @ jods4 - рдореБрдЭреЗ рдЦреЗрдж рд╣реИ рдХрд┐ рдореИрдВ рдпрд╣рд╛рдВ рдЖрдкрдХреЗ рд╕реБрдЭрд╛рд╡ рдХрд╛ рдЬрд╡рд╛рдм рдирд╣реАрдВ рджреЗ рд░рд╣рд╛ рд╣реВрдВред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ 'рджрдлрди' рдирд╣реАрдВ рд╣реЛрдЧрд╛ред _

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдлреАрдЪрд░ ('рдЯрд╛рдЗрдк рдкреНрд░реЙрдкрд░реНрдЯреА рдЯрд╛рдЗрдк') рдХрд╛ рдирд╛рдордХрд░рдг рдмрд╣реБрдд рднреНрд░рд╛рдордХ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╕рдордЭрдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рдХрдард┐рди рдерд╛ рдХрд┐ рдпрд╣рд╛рдБ рд╡рд░реНрдгрд┐рдд рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреНрдпрд╛ рд╣реИ рдФрд░ рдкрд╣рд▓реА рдЬрдЧрд╣ рдореЗрдВ рдЗрд╕рдХрд╛ рдХреНрдпрд╛ рдЕрд░реНрде рд╣реИ!

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЧреБрдг рдирд╣реАрдВ рд╣реИрдВ! undefined рдФрд░ null (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпреЗ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдХреЗрд╡рд▓ рд╣рд╛рд▓рд┐рдпрд╛ рдЬреЛрдбрд╝ рдирд╣реАрдВ рд╣реИрдВ)ред рдЖрджрд┐рдо number , string , boolean рд╢рд╛рдпрдж рд╣реА рдХрднреА рдПрдХ рд╕рдВрдкрддреНрддрд┐ (рдЬреИрд╕реЗ 2 ["рдкреНрд░реЛрдк") рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдорд┐рдд рд╣реЛрддреЗ рд╣реИрдВ? рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рд▓рдЧрддрд╛ рд╣реИ, рдпрд╣ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдПрдХ рдЧрд▓рддреА рд╣реИ)

рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдирд╛рдо рджреЗрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдЗрдВрдЯрд░рдлреЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рдХрд╛рд░ рд╕рдВрджрд░реНрдн рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ ред рдпрд╣рд╛рдВ рд╡рд┐рд╖рдп рдПрдХ рдирдП 'рдкреНрд░рдХрд╛рд░' рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡реЗрд░рд┐рдПрдмрд▓ рдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдмрд╣реБрдд рд╣реА рдЦрд╛рд╕ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдореВрд▓реНрдп _must рд╕рдВрдХрд▓рди рд╕рдордп_ рдкрд░ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред

рдпрд╣ рдЕрддреНрдпрдзрд┐рдХ рд▓рд╛рднрдХрд╛рд░реА рд╣реЛрддрд╛ рдпрджрд┐ рдЗрд╕реЗ рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рдмрд╛рд╣рд░ рд╡рд░реНрдгрд┐рдд рдФрд░ рд╕рд░рд▓ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛:

interface MyInterface {
  prop1: number;
  prop2: string;
}

let prop1Name = "prop1";
type Prop1Type = MyInterface[prop1Name]; // Prop1Type is now 'number'

let prop2Name = "prop2";
type Prop2Type = MyInterface[prop2Name]; // Prop2Type is now 'string'

let prop3Name = "prop3";
type NonExistingPropType = MyInterface[prop3Name]; // Compilation error: property 'prop3' does not exist on 'MyInterface'.

let randomString = createRandomString();
type NotAvailablePropType = MyInterface[randomString]; // Compilation error: value of 'randomString' is not known at compile time.

_Edit: рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдпрд╣ рдкрддрд╛

_Edit 2: рд╢рд╛рдпрдж рдпрд╣ рдХреЗрд╡рд▓ const рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдЬрдм рдПрдХ рдЪрд░ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛? _

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореВрд▓ рдЙрджреНрджреЗрд╢реНрдп рдХреЗрд╡рд▓ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдпрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рдмрд╣реБрдд рд╣реА рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╡рд┐рдзрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИ? рдЬреИрд╕реЗ

function func(someString: string): MyInterface[someString] {
  ..
}

let x = func("prop"); // x gets the type of MyInterface.prop

рдХреНрдпрд╛ рдореИрдВрдиреЗ рдЗрд╕реЗ рдореВрд▓ рд░реВрдк рд╕реЗ рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдкрд░реЗ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдХрд┐рдпрд╛ рд╣реИ?

рдпрд╣ рдПрдХ рдРрд╕реЗ рдорд╛рдорд▓реЗ рдХреЛ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓реЗрдЧрд╛ рдЬрд╣рд╛рдВ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдирд╣реАрдВ рд╣реИ, рдЕрд░реНрдерд╛рдд рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдЬреНрдЮрд╛рдд рдирд╣реАрдВ рд╣реИ? рдЬреИрд╕реЗ

let x = func(getRandomString()); // What type if inferred for 'x' here?

рдХреНрдпрд╛ рдпрд╣ рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреА, рдпрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ any рд╢рд╛рдпрдж рд╣реЛрдЧрд╛?

(рдкреБрдирд╢реНрдЪ: рдпрджрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд░рд╛рджрд╛ рдерд╛, рддреЛ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрдЭрд╛рд╡ рджреВрдВрдЧрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рдХрд╛рд░ рдкреНрд░рдХрд╛рд░ рд╕рдВрджрд░реНрдн рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╡рд┐рдзрд┐ рддрд░реНрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ - рдЬрд┐рддрдирд╛ рд▓рдВрдмрд╛ рдпрд╣ рдирд┐рдХрд▓рд╛, рдпрд╣ рд╡рд░реНрддрдорд╛рди рд╢реАрд░реНрд╖рдХ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рдФрд░ рд╡реНрдпрд╛рдЦреНрдпрд╛рддреНрдордХ рд╣реИред)

рдпрд╣рд╛рдБ рдПрдХ рд╕рд░рд▓ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд) рдЬреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкреНрд░рдХрд╛рд░ рд▓рд┐рдЦреЗрдВ, рдЬреЛ:

  • рд╡рд╛рджрд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рд╕реЗ рдпреБрдХреНрдд рдПрдХ рд╡рд╕реНрддреБ рд▓реЗрддрд╛ рд╣реИ, рдФрд░
  • рдПрдХ рд╣реА рд╡рд╕реНрддреБ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде, рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЙрдЪрд┐рдд рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИред
function awaitObject(obj) {
  var result = {};
  var wait = Object.keys(obj)
    .map(key => obj[key].then(val => result[key] = val));
  return Promise.all(wait).then(_ => result)
}

рдЬрдм рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд╕реНрддреБ рдкрд░ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

var res = awaitObject({a: Promise.resolve(5), b: Promise.resolve("5")})

рдкрд░рд┐рдгрд╛рдо res рдХрд╛ рдкреНрд░рдХрд╛рд░ {a: number; b: string} рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП


рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд╕рд╛рде (@Artazor рджреНрд╡рд╛рд░рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛) рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реЛрдВрдЧреЗ

awaitObject<p, T[p]>(obj: {...p: Promise<T[p]>}):Promise<{...p: T[p]}>

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдКрдкрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, Promise<...> ^ ^ рдЧрд╛рдпрдм рдерд╛

@ рд╕рдВрднрд╛рд╡рдирд╛

рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдХрд╣реАрдВ рднреА рдореБрдЭреЗ рдПрдХ рдЙрдЪрд┐рдд рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдорд┐рд▓рд╛ рд╣реИ рдФрд░ рд╕реНрдкрд╖реНрдЯ рдХрдо рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реИ рдЬреЛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рд╕реЗ _detached_ рд╣реИрдВ рдФрд░ рд╢рдмреНрджрд╛рд░реНрде рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдХрд┐рдирд╛рд░реЗ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛; рдореВрд▓ рд░реВрдк рдореЗрдВ рднреА рдХреБрдЫ:

function func<T extends object>(name: string): T[name] {
 ...
}
  1. рдПрдХ рдкреНрд░рднрд╛рд╡реА рдФрд░ рд╡реНрдпрд╛рдЦреНрдпрд╛рддреНрдордХ рд╢реАрд░реНрд╖рдХ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХрдо рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ 'рдЯрд╛рдЗрдк рдкреНрд░реЙрдкрд░реНрдЯреА рдЯрд╛рдЗрдк' рднреНрд░рд╛рдордХ рд╣реИ рдФрд░ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╡реНрдпрд╛рдЦреНрдпрд╛рддреНрдордХ рдирд╛рдо рдирд╣реАрдВ рд╣реИ, рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ рд▓реЗрдХрд┐рди рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ)ред рдореЗрд░рд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╢реАрд░реНрд╖рдХ рдерд╛ _Interface рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рдХрд╛рд░ рд╕рдВрджрд░реНрдн рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╡рд┐рдзрд┐ рдЖрд░реНрдЧреНрдпреБрдореЗрдВрдЯреНрд╕_ рджреНрд╡рд╛рд░рд╛ (рдпрд╣ рдорд╛рдирддреЗ рд╣реБрдП рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕ рдХреЗ рджрд╛рдпрд░реЗ рдХреЛ рдЧрд▓рдд рдирд╣реАрдВ рд╕рдордЭрд╛)ред
  2. рдЗрд╕ рдмрд╛рдд рдХрд╛ рд╕реНрдкрд╖реНрдЯ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрджрд┐ name рд╕рдВрдХрд▓рд┐рдд рд╕рдордп, рдЕрд╢рдХреНрдд, рдпрд╛ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдкрд░ рдЬреНрдЮрд╛рдд рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕реЗ func<MyType>(getRandomString()) , func<MyType>(undefined) ред
  3. рдЗрд╕ рдмрд╛рдд рдХрд╛ рд╕реНрдкрд╖реНрдЯ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрджрд┐ T рдПрдХ рдЖрджрд┐рдо рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬреИрд╕реЗ number рдпрд╛ null ред
  4. рдЗрд╕ рдмрд╛рдд рдкрд░ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рд╡рд░рдг рдирд╣реАрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдореЗрдВ T[name] рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдФрд░ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЕрдЧрд░ name рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдореЗрдВ рдкреБрди: рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рддрд░рд╣ рдЗрд╕рдХрд╛ рдореВрд▓реНрдп рдЕрдм рд╕рдВрдХрд▓рд┐рдд рд╕рдордп рдкрд░ рдирд╣реАрдВ рдЬрд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?
  5. рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреА рдХреЛрдИ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдирд╣реАрдВ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП T["propName"] рдпрд╛ T[propName] рдХрд╛рдо рд╣реЛрдЧрд╛? рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдпрд╛ рдЪрд░ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рдмрд┐рдирд╛, рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ - рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ!
  6. рдХреЛрдИ рдЙрд▓реНрд▓реЗрдЦ рдпрд╛ рдЪрд░реНрдЪрд╛ рдирд╣реАрдВ рд╣реИ рдЕрдЧрд░ T[name] рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдиреНрдп рдорд╛рдкрджрдВрдбреЛрдВ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рд╕реНрдХреЛрдк рдХреЗ рдмрд╛рд╣рд░ рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреИрд╕реЗ
function func<T extends object>(name: string, val: T[name]) {
 ...
}
type A = { abcd: number };
const name = "abcd";
let x: A[name]; // Type of 'x' resolves to 'number'

_7ред рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ typeof (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рдмрд╛рдж рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдкрд╣рд▓реЗ рд╣реА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рд░рд▓ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреА рдХреЛрдИ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЪрд░реНрдЪрд╛ рдирд╣реАрдВ:

function get<T, V>(obj: T, propName: string): V {
    return obj[propName];
}

type MyType = { abcd: number };
let x: MyType  = { abcd: 12 };

let result = get<MyType, typeof x.abcd>(x, "abcd"); // Type of 'result' is 'number'

рдирд┐рд╖реНрдХрд░реНрд╖ рдореЗрдВ: рдпрд╣рд╛рдВ рдХреЛрдИ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рд╕реНрддрд╛рд╡ рдирд╣реАрдВ рд╣реИ, рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧ рдХреЗрд╕ рдкреНрд░рджрд░реНрд╢рдиреЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реИред рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ рдХрд┐ рдпрд╣ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЯреАрдо рджреНрд╡рд╛рд░рд╛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдП рдЧрдП рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдмреНрдпрд╛рдЬ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдпрд╣ рдЙрдирдХреЗ рдорд╛рдирдХреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдЦреЗрдж рд╣реИ рдХрд┐ рдЕрдЧрд░ рдореИрдВ рдпрд╣рд╛рдВ рдереЛрдбрд╝рд╛ рдХрдареЛрд░ рд▓рдЧ рд╕рдХрддрд╛ рд╣реВрдВ (рдореЗрд░реЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд╣реАрдВ), рд▓реЗрдХрд┐рди рдореЗрд░реА рдХреЛрдИ рднреА рдЖрд▓реЛрдЪрдирд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдирд╣реАрдВ рд╣реИ рдпрд╛ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдд рдирд╣реАрдВ рд╣реИред

рдХреНрдпрд╛ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрдЯрд╛-рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЙрд╕ рджреВрд░ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?

JS рдПрдХ рдЧрддрд┐рд╢реАрд▓ рднрд╛рд╖рд╛ рд╣реИ, рдХреЛрдб рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдордирдорд╛рдиреЗ рддрд░реАрдХреЗ рд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИред
рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╣рдо рдЬреЛ рдореЙрдбрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЙрд╕рдХреА рд╕реАрдорд╛рдПрдВ рд╣реИрдВ рдФрд░ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЖрдирд╛ рдЖрд╕рд╛рди рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдЖрдк рдЯреАрдПрд╕ рдореЗрдВ рдореЙрдбрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред
рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ: рдпрд╣ рдХрд╣рд╛рдБ рддрдХ рдЙрдЪрд┐рдд рдФрд░ рдЙрдкрдпреЛрдЧреА рд╣реИ?

@Spion рд╕реЗ рдЕрдВрддрд┐рдо рдЙрджрд╛рд╣рд░рдг ( awaitObject ) рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╣реИ:

  • _Very complex_ рднрд╛рд╖рд╛ рдХреА рджреГрд╖реНрдЯрд┐ рд╕реЗ (рдореИрдВ рдпрд╣рд╛рдБ @malibuzios рд╕реЗ рд╕рд╣рдордд рд╣реВрдБ)ред
  • рдкреНрд░рдпреЛрдЬреНрдпрддрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ _Very рд╕рдВрдХреАрд░реНрдг_ред рд╡рд╣ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд╛рдзрд╛рдУрдВ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

BTW @spion рд╕реЗ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рд╕рд╣реА рдирд╣реАрдВ рдорд┐рд▓рд╛ ... рдпрд╣ рдПрдХ Promise рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИред

рд╣рдо рдореВрд▓ рдореБрджреНрджреЗ рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИрдВ, рдЬреЛ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдПрдкреАрдЖрдИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдерд╛, рдЬреЛ рдХрд┐ _.pluck рдЬреИрд╕реЗ рдлрд╝реАрд▓реНрдб рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реЗрддреЗ рд╣реИрдВ
рд╡реЗ API _should be_ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╕рд╛рдорд╛рдиреНрдп рд╣реИрдВ рдФрд░ рд╡реЗ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИрдВред рд╣рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП { ...p: T[p] } рдЬреИрд╕реЗ рдореЗрдЯрд╛-рдореЙрдбрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
рдУрдкреА рдореЗрдВ рдХрдИ рдЙрджрд╛рд╣рд░рдг рд╣реИрдВ, рдиреЗрдордлреНрд▓реЛ рдореБрджреНрджреЗ рдореЗрдВ
рдПрдХ рдЕрд▓рдЧ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЙрди рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓реЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдКрдкрд░ рдореЗрд░реА рдЯрд┐рдкреНрдкрдгреА рджреЗрдЦреЗрдВред

@ jods4 рдЗрд╕рдХреА рд╕рдВрдХреАрд░реНрдг рдирд╣реАрдВ рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдореЙрдбрд▓рд┐рдВрдЧ рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИред рдореИрдВ рдХрд╣реВрдБрдЧрд╛ рдХрд┐ TS рдкреНрд░рдХрд╛рд░ рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдмрдбрд╝реЗ рдЧрд╛рдпрдм рднрд╛рдЧреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХред @Artazor https://github.com/Microsoft/TypeScript/issues/1295#issuecomment -177287714 рдКрдкрд░ рджрд┐рдП рдЧрдП рд╕рд░рд▓ рд╕рд╛рдорд╛рди рд╕реЗ рдКрдкрд░ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рд╣реИрдВ, sql рдХреНрд╡реЗрд░реА рдмрд┐рд▓реНрдбрд░ - рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ рдФрд░ рдЗрд╕реА рддрд░рд╣ред

рдпрд╣ рдмреНрд▓реВрдмрд░реНрдб рдореЗрдВ awaitObject ред рдЗрд╕рдХреА рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд┐рдзрд┐ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдмреЗрдХрд╛рд░ рд╣реИред

рдПрдХ рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╛рдзрд╛рди рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕рд░рд▓ рдФрд░ рдЬрдЯрд┐рд▓ рджреЛрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдЖрдзреЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдПрдХ рдХрдордЬрд╝реЛрд░ рд╕рдорд╛рдзрд╛рди рдкрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдЕрдиреБрдХреВрд▓рддрд╛ рдХреА рд╕рдорд╕реНрдпрд╛ рдкреИрджрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ рдпрджрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рдПрдХ рдХреЛ рдЕрдкрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛред

рд╣рд╛рдВ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ @Artazor рдиреЗ рдЙрди рд╕рднреА рдкрд╣рд▓реБрдУрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдФрд░ рдЕрдиреНрд╡реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдХрд╛рдо рдХрд┐рдпрд╛, рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдирд╣реАрдВ рд╕реЛрдЪрд╛ рдерд╛ред рдореИрдВ рдирд╣реАрдВ рд░рд╣реВрдБрдЧрд╛ рдХрд┐ рд╣рдо рдореВрд▓ рд╕рдорд╕реНрдпрд╛ рд╕реЗ рднрдЯрдХ рдЧрдП рд╣реИрдВ, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЗрд╕рдХреА рдмреЗрд╣рддрд░ рд╕рдордЭ рд╣реИред

рд╣рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрд╣рддрд░ рдирд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдореИрдВ рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпреЗ рдЪреАрдЬреЗрдВ рдЖрдорддреМрд░ рдкрд░ рд╕рд╣реА рдирд╣реАрдВ рд▓рдЧрддреА рд╣реИрдВред "рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЗрдирд░рд┐рдХ" рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ?

@ рд╕реНрдерд╛рди , рдХреЗрд╡рд▓

awaitObject<p,T[p]>(obj: {...p:Promise<T[p]>}): Promise<{...p:T[p]}>

(рдЖрдкрдиреЗ рдЖрдЙрдЯрдкреБрдЯ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдореЗрдВ рдПрдХ рдкреНрд░реЙрдорд┐рд╕ рдорд┐рд╕ рдХрд┐рдпрд╛ рд╣реИ)
-)

@ jods4 , рдореИрдВ @spion рд╕реЗ рд╕рд╣рдордд рд╣реВрдВ
рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреА рдмрд╣реБрдд рд╕рд╛рд░реА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ рдЬрд╣рд╛рдВ { ...p: T[p] } рдХрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИред рдХрд┐рд╕реА рдПрдХ рдХрд╛ рдирд╛рдо: рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ + рдкреНрд░рд╡рд╛рд╣ / redux

@spion @Artazor
рдореБрдЭреЗ рдмрд╕ рдЪрд┐рдВрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рдЬрдЯрд┐рд▓ рд╣реЛ рд░рд╣реА рд╣реИред

рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдкреАрдЫреЗ рдХреА рдкреНрд░реЗрд░рдгрд╛ рдмрд╣ рдЧрдИ рд╣реИред рдореВрд▓ рд░реВрдк рд╕реЗ рдпрд╣ рдПрдкреАрдЖрдИ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдерд╛ рдЬреЛ рдПрдХ рд╡рд╕реНрддреБ рдХреНрд╖реЗрддреНрд░ рдХреЛ рджрд░реНрд╢рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЕрдм рдпрд╣ рдЬреНрдпрд╛рджрд╛рддрд░ рдПрдкреАрдЖрдИ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирдХреНрд╢реЗ рдпрд╛ рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░рддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрджрд┐ рд╣рдо рдПрдХ рдкрддреНрдерд░ рд╕реЗ рджреЛ рдкрдХреНрд╖рд┐рдпреЛрдВ рдХреЛ рдорд╛рд░ рд╕рдХрддреЗ рд╣реИрдВ рддреЛ рдореИрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣реВрдВред

рдЕрдЧрд░ рд╣рдо APIs рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рд╕рдорд╕реНрдпрд╛ рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ T[p] рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдкреВрд░реНрдг рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ (рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдХреНрдпреЛрдВ рдХрд╣рд╛)ред

рд╢реБрджреНрдзрддрд╛ рдХреЗ рд▓рд┐рдП _Just_ awaitObject рдХреЛ рдЧреИрд░-рд╡рд╛рджрд╛ рдЧреБрдгреЛрдВ рдХреЛ рднреА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХрдо рд╕реЗ рдХрдо Bluebird props рдХрд░рддрд╛ рд╣реИред рддреЛ рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реИ:

awaitObject<p,T[p]>(obj: { ...p: T[p] | Promise<T[p]> }): Promise<T>

рдореИрдВрдиреЗ рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЛ Promise<T> рдмрджрд▓ рджрд┐рдпрд╛ рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдЕрдВрдХрди рдХрд╛рдо рдХрд░реЗрдЧрд╛ред
рдЕрдиреНрдп рдЕрддрд┐рднрд╛рд░ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╛рджрд╛ рдХрд░рддрд╛ рд╣реИ (рдЗрд╕рдХрд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдФрд░ рднреА рдордЬреЗрджрд╛рд░ рд╣реИ)ред рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ { ...p } рдиреЛрдЯреЗрд╢рди рдХреЛ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдПрдХ рдЦрд░рд╛рдм рдореИрдЪ рдорд╛рдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЗрди рд╕рднреА рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рдХрдард┐рди рдХрд╛рдо рд╣реИред рдЕрдЧрд░ рдЖрдк рдЗрд╕реЗ рдЖрдЧреЗ рдмрдврд╝рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдЕрдЧрд▓рд╛ рдХрджрдо рд╣реИред

@spion @ jods4

рдореИрдВ рдпрд╣ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдЬреЗрдирд░рд┐рдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ рдФрд░ рди рд╣реА рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╣реБрд░реВрдкреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╕реЗ рдпреБрдХреНрдд рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИ (рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рдХреБрдЫ "рдЙрдиреНрдирдд" рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде), рдЬреЛ рдЕрд╡рдзрд╛рд░рдгрд╛ рдореЗрдВ typeof рд╕реЗ рджреВрд░ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг:

type MyType = { abcd: number };
let y: MyType["abcd"]; // Technically this could also be written as MyType.abcd

рдЕрдм рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ:

type MyType = { abcd: number };
let x: MyType;

let y: typeof x.abcd;

typeof рд╕рд╛рде рджреЛ рдореБрдЦреНрдп рдЕрдВрддрд░ рд╣реИрдВред typeof рд╡рд┐рдкрд░реАрдд, рдпрд╣ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдмрдЬрд╛рдп рдЯрд╛рдЗрдк (рдХрдо рд╕реЗ рдХрдо рдЧреИрд░-рдЖрджрд┐рдо рд▓реЛрдЧреЛрдВ, рдПрдХ рддрдереНрдп рдЬреЛ рдЕрдХреНрд╕рд░ рдпрд╣рд╛рдВ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ) рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ (рдФрд░ рдпрд╣ рдПрдХ рдкреНрд░рдореБрдЦ рдмрд╛рдд рд╣реИ) рдЗрд╕реЗ рд╢рд╛рдмреНрджрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рд░рд╛рдВрдХ (рдЬрд┐рд╕реЗ рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдЬреНрдЮрд╛рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП) рдХреЛ рд╕рдВрдкрддреНрддрд┐ рдкрде рд╡рд┐рд╡рд░рдгрдХ, рдФрд░ рдЬреЗрдирд░рд┐рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:

const propName = "abcd";
let y: MyType[propName];
// Or with a generic parameter:
let y: T[propName];

рд╣рд╛рд▓рд╛рдБрдХрд┐ рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ typeof рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХреЛрдВ рдХреЗ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдмрдврд╝рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рдерд╛ (рдЗрд╕рдореЗрдВ рд╡рд╣ рдорд╛рдорд▓рд╛ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬрд╣рд╛рдБ x рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд╣реИ):

let x: MyType;
const propName = "abcd";
let y: typeof x[propName];

рдФрд░ рдЗрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреБрдЫ рд▓рдХреНрд╖реНрдп рдорд╛рдорд▓реЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

function get<T>(propName: string, obj: T): typeof obj[propName]

typeof рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдШреЛрдВрд╕рд▓реЗ рдХреЗ рд╢рд┐рдХрд╛рд░ рдХреЗ рд╕реНрддрд░ рдХреА рдЕрдирд┐рд╢реНрдЪрд┐рдд рдорд╛рддреНрд░рд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ:

let y: typeof x.prop.childProp.deeperChildProp

рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рд╕реНрддрд░ рдкрд░ рдЬрд╛рддрд╛ рд╣реИред Ie рдиреЗ рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рдмрдирд╛рдИ рд╣реИ (рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореБрдЭреЗ рдкрддрд╛ рд╣реИ) рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:

let y: MyType["prop"]["childProp"]["deeperChildProp"];
// Or alternatively
let y: MyType["prop.childProp.deeperChildProp"];

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд╛ рджрд╛рдпрд░рд╛ (рдпрджрд┐ рдЗрд╕реЗ рдЕрд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд╕реНрддрд░ рдкрд░ рдкреНрд░рд╕реНрддрд╛рд╡ рднреА рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ) рдмрд╣реБрдд рд╕рдВрдХреАрд░реНрдг рд╣реИред рдпрд╣ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ), рдЬреЛ рдХрдИ рд▓реЛрдЧреЛрдВ рдХреЛ рдЗрд╕реЗ рдмрдврд╝рд╛рд╡рд╛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрддреНрд╕реБрдХ рдмрдирд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдпрд╣ рднрд╛рд╖рд╛ рд╕реЗ рдореВрд▓реНрдпрд╡рд╛рди рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рдХрд╛ рднреА рдЙрдкрднреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИред рдПрдХ рд╡реНрдпрд╛рдкрдХ рдпреЛрдЬрдирд╛ рдФрд░ рдбрд┐рдЬрд╛рдЗрди-рдЙрдиреНрдореБрдЦ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдмрд┐рдирд╛, рдпрд╣ рдЬрд▓реНрджрдмрд╛рдЬреА рдореЗрдВ рдХреБрдЫ рдРрд╕рд╛ рдкреЗрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╛рд╕рдордЭ рд▓рдЧрддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЗрд╕ рддрд╛рд░реАрдЦ рдХреЛ рднреА рд╕реНрдкрд╖реНрдЯ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдирд╣реАрдВ рд╣реИред

_Edits: рдХреЛрдб рдореЗрдВ рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рдЧрд▓рддрд┐рдпреЛрдВ рдХреЛ рд╕рд╣реА рдХрд┐рдпрд╛ example_

рдореИрдВрдиреЗ typeof рд╡рд┐рдХрд▓реНрдк рдкрд░ рдереЛрдбрд╝рд╛ рд╢реЛрдз рдХрд┐рдпрд╛ рд╣реИ:

typeof x["abcd"] рдФрд░ typeof x[42] рд▓рд┐рдП рднрд╡рд┐рд╖реНрдп рдХреА рднрд╛рд╖рд╛ рдХрд╛ рд╕рдорд░реНрдерди рд╕реНрд╡реАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ , рдФрд░ рдЕрдм # 6606 рдХреЗ рдЕрдВрддрд░реНрдЧрдд рдЖрддрд╛ рд╣реИ, рдЬреЛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЕрдзреАрди рд╣реИ (рдПрдХ рдХрд╛рд░реНрдп рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ)ред

рдпрд╣ рдЖрдзрд╛ рд░рд╛рд╕реНрддрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрдирдХреА рдЬрдЧрд╣ рдкрд░, рдмрд╛рдХреА рдХрдИ рдЪрд░рдгреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

(1) рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд╕реНрдерд┐рд░рд╛рдВрдХ (рдпрд╛ рд╕рдордХрд╛рд▓рд┐рдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВ - рдЯреБрдкрд▓реНрд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?) рдкреНрд░рдХрд╛рд░ рдХреЗ рднрд╛рд╡реЛрдВ рдореЗрдВ рдЧреБрдг рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ, рдЬреИрд╕реЗ:

let x: MyType;
const propName = "abcd";
let y: typeof x[propName];

(2) рдЗрди рд╕реНрдкреЗрд╕рд░реЛрдВ рдХреЛ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ

let x: T; // Where T should extend 'object'
const propName = "abcd";
let y: typeof x[propName];

(3) рдЗрди рд╡рд┐рдирд┐рд░реНрджреЗрд╢рдХреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ, рдФрд░ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ "рддрд░реНрдХреЛрдВ" рдХреЛ рд╕рдВрджрд░реНрдн рддрд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ ( typeof list[0] рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЛрдВ рдЬреИрд╕реЗ pluck рдХреЛ рдХрд╡рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ:

function get<T extends object>(obj: T, propertyName: string): typeof obj[propertyName];
function pluck<T extends object>(list: Array<T>, propertyName: string): Array<typeof list[0][propertyName]>;

( object рдкреНрд░рдХрд╛рд░ рдпрд╣рд╛рдБ # 1809 рдкрд░ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╣реИ)

рдпрджреНрдпрдкрд┐ рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА (рдЬреИрд╕реЗ typeof obj[propName][nestedPropName] рд╕рдорд░реНрдерди рдХрд░ рд╕рдХрддрд╛ рд╣реИ) рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдпрд╣ рд╡реИрдХрд▓реНрдкрд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдпрд╣рд╛рдВ рд╡рд░реНрдгрд┐рдд рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЛ рдХрд╡рд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдРрд╕реЗ рдЙрджрд╛рд╣рд░рдг рд╣реИрдВ рдЬреЛ рдЗрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ (рдПрдХ рдкрд░рд┐рджреГрд╢реНрдп рдЬреЛ рдорди рдореЗрдВ рдЖрддрд╛ рд╣реИ рд╡рд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрджрд╛рд╣рд░рдг рдмрд┐рд▓реНрдХреБрд▓ рднреА рдкрд╛рд░рд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдПрдХ рдорд╛рдорд▓реЗ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ)ред

_Edits: code_ рдореЗрдВ рдХреБрдЫ рдЧрд▓рддрд┐рдпреЛрдВ рдХреЛ рд╕реБрдзрд╛рд░рд╛

@ рдорд╛рд▓рд┐рдмреБрдЬрд╝рд┐рдпреЛрд╕
рдХреБрдЫ рд╡рд┐рдЪрд╛рд░:

  • рдпрд╣ рдПрдкреАрдЖрдИ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдХреЙрд▓рд░ рдХреА рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд╣рдореЗрдВ рдЕрднреА рднреА рдХреЙрд▓ рд╕рд╛рдЗрдЯ рдкрд░ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ nameof рдпрд╛ Expression ред
  • рдпрд╣ .d.ts рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЖрдо рддреМрд░ рдкрд░ TS рдХрд╛рд░реНрдпреЛрдВ / рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиреЛрдВ рдореЗрдВ рд╡реИрдзрд╛рдирд┐рдХ рд░реВрдк рд╕реЗ рдХрдордЬреЛрд░ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕рддреНрдпрд╛рдкрди рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реЛрдЧрд╛ред

рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рдореИрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддрд╛ рд╣реВрдВ, рдЙрддрдирд╛ рдЕрдзрд┐рдХ Expression<T, U> рдЙрд╕ рддрд░рд╣ рдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдзрд╛рди рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИред рдпрд╣ рдХреЙрд▓ рд╕рд╛рдЗрдЯ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИ, рдкрд░рд┐рдгрд╛рдо рдХреА рдЯрд╛рдЗрдкрд┐рдВрдЧ рдФрд░ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдмрд╛рдВрдЭ + рд╕рддреНрдпрд╛рдкрди рдпреЛрдЧреНрдп рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

@ jods4

рдЖрдкрдиреЗ рдкрд┐рдЫрд▓реЗ рдЯрд┐рдкреНрдкрдгреА рдХреЗ рддрд░реАрдХреЗ рдореЗрдВ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ pluck рдХреЛ рднрд╛рд╡реЛрдВ рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрджреНрдпрдкрд┐ рдореИрдВрдиреЗ C # рд╕реЗ рдмрд╣реБрдд рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдиреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛, рдореИрдВрдиреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдирдХреЗ рд╕рд╛рде рдХрднреА рдкреНрд░рдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдЙрдирдХреА рдмрд╣реБрдд рдЕрдЪреНрдЫреА рд╕рдордЭ рдирд╣реАрдВ рд╣реИред

рд╡реИрд╕реЗ рднреА, рд╕рд┐рд░реНрдл рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдЯрд╛рдЗрдк рдЯрд╛рдЗрдк рддрд░реНрдХ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ pluck рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдХреЛрдИ рднреА map рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рд╡рд╣реА рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА ( рдпрд╣ рдЕрдиреБрдорд╛рди рд╣реИ) рдФрд░ рдпрд╣ рднреА рдкреВрд░реНрдг рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдБрдЪ рдФрд░ рдкреВрд░реНрдгрддрд╛ рджреЗрдЧрд╛:

let x = [{name: "John", age: 34}, {name: "Mary", age: 53}];

let result = x.map(obj => obj.name);
// 'result' is ["John", "Mary"] and its type inferred as 'string[]' 

рдЬрд╣рд╛рдБ map (рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рдЕрддреНрдпрдзрд┐рдХ рд╕рд░рд▓реАрдХреГрдд) рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

map<U>(mapFunc: (value: T) => U): U[];

рдПрдХ рд╣реА рд▓реИрдВрдмрдбрд╛ рдХреЗ рдХрд┐рд╕реА рднреА рдкрд░рд┐рдгрд╛рдо рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдЪрд╛рд▓рди рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ 'рдЯреНрд░рд┐рдХ' рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЬрд┐рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ) рдФрд░ рдЗрд╕рдХреЗ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХреЛ рдЗрд╕рдореЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВ:

function thisIsATrick<T, U>(obj: T, onlyPassedToInferTheReturnType: () => U): U {
   return;
}

let x = {name: "John", age: 34};

let result = thisIsATrick(x, () => x.age) // Result inferred as 'number' 

_Edit: рдпрд╣ рдпрд╣рд╛рдБ рдПрдХ рдореЗрдордиреЗ рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рди рдХреЗрд╡рд▓ рдЦреБрдж рдмрд╛рдд! рд╣рд╛рд▓рд╛рдВрдХрд┐ рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ (рдЬреИрд╕реЗ x.prop.Childprop ) рдЬреИрд╕реЗ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдпрд╛ рдЕрд╢рдХреНрдд рд╕рдВрджрд░реНрдн рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕реЗ рд▓рдВрдмреЛрджрд░ рдореЗрдВ рд░рдЦрдирд╛, рдЬрд┐рд╕реЗ рдЬрд░реВрд░реА рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ ред_

рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдБ рдХрд┐ рдореИрдВ рдпрд╣рд╛рдБ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рд╕реЗ рдмрд╣реБрдд рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реВрдБред рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдореБрдЭреЗ рдХрднреА рднреА рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдорд╣рд╕реВрд╕ рдирд╣реАрдВ рд╣реБрдИ рдЬреЛ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд╛рдо рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддрд╛ рд╣реИред рдкреНрд░рдХрд╛рд░ рддрд░реНрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ (рдЬрд╣рд╛рдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдлрд╛рдпрджреЗ рднреА рд╣реИрдВ) рдкрд╛рд╕ рдХрд░рдирд╛ рдЖрдорддреМрд░ рдкрд░ рдХрдИ рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред

рдЬрд┐рд╕ рдХрд╛рд░рдг рд╕реЗ рдореИрдВрдиреЗ typeof рд╡реИрдХрд▓реНрдкрд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдерд╛, рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рд╕рдорд╛рди рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рдЧрддрд╛ рд╣реИ рдФрд░ рдЬреЛ рд▓реЛрдЧ рдпрд╣рд╛рдВ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдореИрдВ рдЦреБрдж рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реВрдВрдЧрд╛? рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛, рдХрднреА рднреА рдЗрд╕рдХреА рдЬрд╝рд░реВрд░рдд рдорд╣рд╕реВрд╕ рдирд╣реАрдВ рд╣реБрдИ (рдпрд╣ рдмрд╕ рдЗрддрдирд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рд▓рдЧрднрдЧ рдХрднреА рднреА рдмрд╛рд╣рд░реА рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реВрдВ рдЬреИрд╕реЗ рдХрд┐ рдЕрдВрдбрд░рд╕реНрдХреЛрд░, рдореИрдВ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдЕрдкрдиреЗ рджреНрд╡рд╛рд░рд╛ рдЖрд╡рд╢реНрдпрдХ рдЖрдзрд╛рд░ рдкрд░ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ)ред

@malibuzios рд╕рдЪ рд╣реИ, pluck рд▓рдВрдмреЛрджрд╛ + map рдЕрдм рдмрд┐рд▓реНрдЯ-рдЗрди рдХреЗ рд╕рд╛рде рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рд╣реИред

рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ рдореИрдВ 5 рдЕрд▓рдЧ-рдЕрд▓рдЧ рдПрдкреАрдЖрдИ рджреЗрддрд╛ рд╣реВрдВ рдЬреЛ рд╕рднреА рддрд╛рд░ рд▓реЗрддреЗ рд╣реИрдВ - рд╡реЗ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВред

@ jods4 рдФрд░ рдЕрдиреНрдп

рдХреЗрд╡рд▓ рдпрд╣ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдЬрдм # 6606 рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдЪрд░рдг 1 рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ (рд╕рдВрдкрддреНрддрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧрд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░рдВрддрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВ) рдпрд╣рд╛рдВ рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдореЗрдВ рд╕реЗ рдХреБрдЫ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЙрддрдиреЗ рд╣реА рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдврдВрдЧ рд╕реЗ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ) рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд╛рдо рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╡рд░рдг)ред

function observeProperty<T, U>(obj: T, propName: string ): Subscriber<U> {
    ....
}

let x = { name: "John", age: 42 };

const propName = "age";
observeProperty<typeof x, typeof x[propName]>(x, propName);

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреА рдорд╛рддреНрд░рд╛ рдЪрд░рдг 2 рдФрд░ 3 рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХрд╛рдлреА рдХрдо рд╣реЛ рд╕рдХрддреА рд╣реИ (рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ 1 рдкрд╣рд▓реЗ рд╕реЗ рд╣реА # 6606 рджреНрд╡рд╛рд░рд╛ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛ)ред рдЪрд░рдг 2 рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде, рдпрд╣ рдЙрд╕ рдорд╛рдорд▓реЗ рдХреЛ рднреА рдХрд╡рд░ рдХрд░реЗрдЧрд╛ рдЬрд╣рд╛рдВ x рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд╣реИ (рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?)ред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХрд╛рд░рдг рдХрд┐ рдореИрдВрдиреЗ рдПрдХ рдмрд╛рд╣рд░реА рд╕реНрдерд┐рд░рд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рди рдХреЗрд╡рд▓ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЛ рджреЛ рдмрд╛рд░ рд▓рд┐рдЦрд╛ рд╣реИ рди рдХреЗрд╡рд▓ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд▓реНрдХрд┐ рдпрд╣ рднреА рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдирд╛рдо рд╣рдореЗрд╢рд╛ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЕрднреА рднреА "рдирд╛рдо рдмрджрд▓реЗрдВ" рдФрд░ "рд╕рднреА рдЦреЛрдЬреЗрдВ" рдЬреИрд╕реЗ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рд╕рдВрджрд░реНрдн ", рдЬреЛ рдореБрдЭреЗ рдПрдХ рдЧрдВрднреАрд░ рдиреБрдХрд╕рд╛рди рд▓рдЧрддрд╛ рд╣реИред

@ jods4 рдореИрдВ рдЕрднреА рднреА рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдореИрдВ рдпрд╣ рд╕реЛрдЪрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдХрд┐ nameof рдФрд░ рдЗрд╕рдХреЗ рд╡реЗрд░рд┐рдПрдВрдЯ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рд╡рд┐рдЪрд╛рд░ рд╣реИред

рдЪреВрдВрдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ, рдЬреИрд╕реЗ рдХреЛрдИ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:

let x: "HELLO"; 

рдХреЛрдИ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рд╢рд╛рдмреНрджрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ

(_Edit: рдЗрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ s рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдореЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИ, рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдкрджреЛрдВ рдкрд░ const рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ ( readonly рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ) рд╣рд╛рд▓рд╛рдВрдХрд┐)ред_) :

function func(const s: string)

string s рд╕рд╛рде рдЬреБрдбрд╝реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ рдХреЛ рдпрд╣рд╛рдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЬреЗрдиреЗрд░рд┐рдХ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рдЗрд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)ред рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд▓рд┐рдЦреВрдВрдЧрд╛ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ):

function func<S extends string>(const s: S)
func("TEST");

рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:

function func(s: "TEST")

рдФрд░ рдЕрдм рдЗрд╕реЗ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХреЛ "рдкрд╛рд╕" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рддрд░реАрдХреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдХреЗ рд╢рдмреНрджрд╛рд░реНрде рдХреЛ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИред

function observeProperty<T, S extends string>(obj: T, const propName: S): Subscriber<T[S]>

x = { name: "John",  age: 33};

observeProperty(x, nameof(x.age))

рдЪреВрдБрдХрд┐ T[S] , рджреЛрдиреЛрдВ T , рдФрд░ S рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИрдВред рд░рди-рдЯрд╛рдЗрдо рдФрд░ рдЯрд╛рдЗрдк рд╕реНрдХреЛрдк рдПрд▓рд┐рдореЗрдВрдЯреНрд╕ (рдЬреИрд╕реЗ T[someString] ) рдХреЛ рдорд┐рдХреНрд╕ рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рджреЛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдВрдпреБрдХреНрдд рд╣реЛрдирд╛ рдЕрдзрд┐рдХ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд╣реИред

_Edits: рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдг ред_

рдЪреВрдВрдХрд┐ рдореИрдВ TS 1.8.7 рдФрд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдЗрд╕ рдмрд╛рдд рдХреА рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рдереА рдХрд┐ рд╣рд╛рд▓ рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ

const x = "Hello";

x рдХрд╛ рдкреНрд░рдХрд╛рд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ "Hello" , (рдпрд╛рдиреА: x: "Hello" ) рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдорд╛рдирд┐рдд рд╣реИ, рдЬреЛ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ (# 6554 рджреЗрдЦреЗрдВ)ред

рддреЛ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЕрдЧрд░ рдХреЛрдИ рдкреИрд░рд╛рдореАрдЯрд░ const (рдпрд╛ рд╢рд╛рдпрдж readonly рднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛?) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдерд╛:?

function func<S extends string>(const s: S): S

рдлрд┐рд░ рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдпрд╣ рдкрдХрдбрд╝ рд╕рдХрддрд╛ рд╣реИ:

let result = func("abcd"); // type of 'result' inferred as the literal type "abcd"

рдЪреВрдВрдХрд┐ рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдирдпрд╛ рд╣реИ рдФрд░ рд╣рд╛рд▓ рдХреА рднрд╛рд╖рд╛ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛:

(1) рдЬрдм const (рдФрд░ рд╢рд╛рдпрдж readonly рд░реВрдк рдореЗрдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ?) рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЪрд░ рдХрд╛ рдПрдХ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╕рдВрдХрд▓рди-рд╕рдордп рдкрд░ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЪрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╕рдорд╛рди рдореВрд▓реНрдп рд╣реЛрддрд╛ рд╣реИ ( рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╣рд╛рд▓рд┐рдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ рдЬреЛ 1.8.x ) рдкрд░ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдЙрджрд╛

const x = "ABCD";

рдХреЗ рдкреНрд░рдХрд╛рд░ x рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рди рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ "ABCD" , рдирд╣реАрдВ string !, рдЬреИрд╕реЗ рдПрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕ рд░рд╛рдЬреНрдп рд╕рдХрддрд╛ рд╣реИ x: "ABCD" ред

(реи) рдпрджрд┐ readonly рдлрд╝рдВрдХреНрд╢рди рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рдереА, рддреЛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ readonly рдкреИрд░рд╛рдореАрдЯрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рдХреЛ рд▓реЗ рдЬрд╛рдПрдЧрд╛ рдЬрдм рдпрд╣ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИ!

function func<S extends string>(readonly str: S);
func("ABCD");

рдпрд╣рд╛рдБ S рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ "ABCD" , рдирд╣реАрдВ string !

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ str рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдирд╣реАрдВ рдерд╛, рддреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдкреБрди: рдЕрд╕рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрд╣ рдЕрдиреБрдорд╛рди рдХреЗрд╡рд▓ string ред

function func<S extends string>(str: S) {
    str = "DCBA"; // This may happen
}

func("ABCD");

(рей) рдЗрд╕рдХрд╛ рд▓рд╛рдн рд▓реЗрдирд╛ рд╕рдВрднрд╡ рд╣реИ рдФрд░ рдореВрд▓ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдПрдХ рд╕рдВрджрд░реНрдн рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕реЗ string to

function get<T extends object, S extends string>(obj: T, readonly propName: S): T[S]

рдЗрд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реНрдХ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА, рдХреНрдпреЛрдВрдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЯрд╛рдЗрдк рддрд░реНрдХ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ:

let x = { name: "John", age: 42 };

get(x, "age"); // result type is inferred to be 'number'
// or for stronger type safety:
get(x, nameof(x.age)); // result type is inferred to be 'number'

_Edits: рдХреБрдЫ рд╡рд░реНрддрдиреА рдФрд░ рдХреЛрдб рдЧрд▓рддрд┐рдпреЛрдВ рдХреЛ рд╕реБрдзрд╛рд░ рджрд┐рдпрд╛ ред_
_Note: рдЗрд╕ рд╕рдВрд╢реЛрдзрд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдЕрдм # 7730._ рдореЗрдВ рднреА рдЯреНрд░реИрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

рдпрд╣рд╛рдБ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧ рд╣реИ (рдпрд╛ "рдЕрдиреБрдХреНрд░рдорд┐рдд рдЬреЗрдирд░рд┐рдХ" рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рдЙрдиреНрд╣реЗрдВ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ) рдЬреЛ @Raynos рдХреЗ рд╕рд╛рде рдЪрд░реНрдЪрд╛ рдореЗрдВ рдЖрдпрд╛ рдерд╛

рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рд╕рд╛рдорд╛рдиреНрдп рдЪреЗрдХрд░ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:

function tArray<T>(f:(t:any) => t is T) {
    return function (a:any): a is Array<T> {
        if (!Array.isArray(a)) return false;
        for (var k = 0; k < a.length; ++k)
            if (!f(a[k])) return false;
        return true;
    }
}

function tNumber(n:any): n is number {
    return typeof n === 'number'
}
var isArrayOfNumber = tArray(tNumber)

function test(x: {}) {
    if (isArrayOfNumber(x)) {
        return x[x.length - 1].toFixed(2); // this type checks
    }
}

рдПрдХ рдмрд╛рд░ рдЬрдм рд╣рдордиреЗ рдЬреЗрдиреЗрд░рд┐рдХ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░ рд▓рд┐рдпрд╛, рддреЛ рд╣рдо рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЪреЗрдХрд░ рднреА рд▓рд┐рдЦ рд╕рдХреЗрдВрдЧреЗ:

function tObject<p, T[p]>(checker: {...p: (t:any) => t is T[p]}) {
  return function(obj: any): obj is {...p: T[p] } {
    for (var key in checker) if (!checker[key](obj[key])) return false;
    return true;
  }
}

рдЬреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ, рд╕рдВрдЦреНрдпрд╛, рдмреВрд▓рд┐рдпрди, рдЕрд╢рдХреНрдд рдФрд░ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдХреЗ рд▓рд┐рдП рдЖрджрд┐рдо рдЪреЗрдХрд░реНрд╕ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдЖрдкрдХреЛ рдЗрд╕ рддрд░рд╣ рдХреА рдЪреАрдЬреЗрдВ рд▓рд┐рдЦрдиреЗ рджреЗрдВрдЧреЗ:

var isTodoList = tObject({
  items: tArray(tObject({text: tString, completed: tBoolean})),
  showCompleted: tBoolean
})

рдФрд░ рдпрд╣ рд╕рд╣реА рд░рдирдЯрд╛рдЗрдо рдЪреЗрдХрд░ _and_ рд╕рдВрдХрд▓рд┐рдд рд╕рдордп рдкреНрд░рдХрд╛рд░ рдЧрд╛рд░реНрдб рдХреЗ рд╕рд╛рде рдкрд░рд┐рдгрд╛рдо рд╣реИ, рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ :)

рдХреНрдпрд╛ рдХрд┐рд╕реА рдиреЗ рдЗрд╕ рдкрд░ рдЕрднреА рддрдХ рдХреЛрдИ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ, рдпрд╛ рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд░рдбрд╛рд░ рдкрд░ рд╣реИ? рдпрд╣ рдПрдХ рдмрдбрд╝рд╛ рд╕реБрдзрд╛рд░ рд╣реЛрдЧрд╛ рдХрд┐ рдХрд┐рддрдиреЗ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ lodash рдпрд╛ ramda рдФрд░ рдХрдИ рдбреЗрдЯрд╛рдмреЗрд╕ рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд╕рдВрдж рд╣реИрдВред

@malibuzios рдХрд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдЖрдк @Artazor рдХреЗ рд╕реБрдЭрд╛рд╡ рдкрд░ рдкрд╣реБрдБрдЪ рд░рд╣реЗ рд╣реИрдВ :)

рдЕрдкрдиреА рдЪрд┐рдВрддрд╛рдУрдВ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:

function func<S extends string>(readonly str: S): T[str] {
 ...
}

рдпрд╣ рд╣реЛрдЧрд╛

function func<S extends string, T[S]>(str: S):T[S] { }

рдЗрд╕ рддрд░рд╣, рдирд╛рдо рдХреЛ рд╕рдмрд╕реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ (рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рд░ рдкреНрд░рдХрд╛рд░) рдХреЗ рд╕рд╛рде рд▓реЙрдХ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрдм рдЗрд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:

func("test")

рдкреНрд░рдХрд╛рд░ S "test" ( string ) рдмрди рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ str рдХреЛ рдПрдХ рдЕрд▓рдЧ рдореВрд▓реНрдп рдкрд░ рднрд░реЛрд╕рд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЕрдЧрд░ рдЖрдкрдиреЗ рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ, рдЬреИрд╕реЗ

str = "other"

рдХрдВрдкрд╛рдЗрд▓рд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рдЬрдм рддрдХ рдХрд┐ рд╡рд┐рдЪрд░рдг рдзреНрд╡рдирд┐ рдореБрджреНрджреЗ рдирд╣реАрдВ рд╣реИрдВ;))

рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдореИрдВ рдПрдХ рдордирдорд╛рдирд╛ рд╕реБрдкрд░ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред

рддреЛ рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рдирд┐рдореНрди рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЬреЛрдбрд╝рдирд╛ рд╣реИ: рдХреЗрд╡рд▓ T[prop] рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдореИрдВ рд╕рд┐рдВрдЯреИрдХреНрд╕ T[...props] рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред рдЬрд╣рд╛рдБ props рдХреЛ T рд╕рджрд╕реНрдпреЛрдВ рдХрд╛ рдПрдХ рд╕рд░рдгреА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рд╕реБрдкрд░ рдкреНрд░рдХрд╛рд░ рд╣реИ T рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд╕рд╛рде T рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд props ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ Sequelize рдореЗрдВ рдЕрддреНрдпрдзрд┐рдХ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ - рдиреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп ORM.js. рд╕реБрд░рдХреНрд╖рд╛ рдХрд╛рд░рдгреЛрдВ рдФрд░ рд╕рд╣реА рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдХреЗрд╡рд▓ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдХреНрд╡реЗрд░реА рдХрд░рдирд╛ рдмреБрджреНрдзрд┐рдорд╛рди рд╣реИ, рдЬрд┐рдирдХрд╛ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рдЕрдХреНрд╕рд░ рд╕реБрдкрд░ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрддрд╛ рд╣реИред

interface IUser {
    id: string;
    name: string;
    email: string;
    createdAt: string;
    updatedAt: string;
    password: string;
    // ...
}

interface Options<T> {
     attributes: (memberof T)[];
}

interface Model<IInstance> {
     findOne(options: Options<IInstance>): IInstance[...options.attributes];
}

declare namespace DbContext {
   define<T>(): Model<T>;
}

const Users = DbContext.define<IUser>({
   id: { type: DbContext.STRING(50), allowNull: false },
   // ...
});

const user = Users.findOne({
    attributes: ['id', 'email', 'name'],
    where: {
        id: 1,
    }
});

user.id
user.email
user.name

user.password // error
user.createdAt // error
user.updatedAt // error

(рдореЗрд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЗрд╕рдореЗрдВ рдСрдкрд░реЗрдЯрд░ memberof , рдЬреЛ рдХрд┐ рдЖрдк рдЗрд╕рд╕реЗ рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ options.attributes рднреА рд╣реИ, рдЬреЛ typeof options.attributes , рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ typeof рдСрдкрд░реЗрдЯрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдмреЗрдорд╛рдиреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИ рдЬреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ))ред

рдЕрдЧрд░ рдХреЛрдИ рдЬреЛрд░ рдирд╣реАрдВ рджреЗрддрд╛, рддреЛ рдореИрдВрдиреЗ рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ред

рдлрдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдЯрд╛рдЗрдк рд╕реЗрдлреНрдЯреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рдпрд╛рдиреА рд░рд┐рдЯрд░реНрди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд░рд┐рдЯрд░реНрди рдЯрд╛рдЗрдк рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдХрд╛рдо рд╣реЛ?

interface A {
     a: string;
}
function f(p: string): A[p] {
    return 'aaa'; // This is string, but can we ensure it is the intended A[p] ?
}

рд╕рд╛рде рд╣реА рдпрд╣рд╛рдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ "рдкреНрд░реЙрдкрд░реНрдЯреА рдЯрд╛рдЗрдк" рдирд╛рдо рдереЛрдбрд╝рд╛ рдЧрд▓рдд рд▓рдЧрддрд╛ рд╣реИред рдпрд╣ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЧреБрдг рд╣реЛрддреЗ рд╣реИрдВ, рдЬреЛ рд▓рдЧрднрдЧ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред

"рд╕рдВрдкрддреНрддрд┐ рд╕рдВрджрд░реНрднрд┐рдд рдкреНрд░рдХрд╛рд░" рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?

рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдЖрдкрдХреА рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ

рдореЗрд░рд╛ рд╡рд┐рдЪрд╛рд░ рдордВрдерди:

let a: A;
function f(p: string): A[p] {
  let x = a[p]; // typeof A[p], only when:
  // 1. p is directly referencing function argument
  // 2. function return type is Property Reference Type

  p = "abc"; // not allowed to assign a new value when p is used on Property Reference Type

  return x; // x is A[p], so okay
}

рдФрд░ рд╡рд╛рдкрд╕реА рд▓рд╛рдЗрди рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╣рдЯрд╛ рджреЗрдВред

рдЖрдкрдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд╕рд╛рде @malibuzios рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рднреА рдЬреЗрдирд░рд┐рдХ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдпрджрд┐ рд╡реЗ рдЕрдиреБрдорд╛рди

Https://github.com/Microsoft/TypeScript/issues/1295#issuecomment -239653337 рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ TS рдЯреАрдо рдХреА рдХреЛрдИ рдЯрд┐рдкреНрдкрдгреА?

@RyanCavanaugh @mhegazy рдЖрджрд┐?

рдирд╛рдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ (рдХрдо рд╕реЗ рдХрдо рд╡рд╣ рд░реВрдк рдЬреЛ @Artazor рдиреЗ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХрд┐рдпрд╛) "рдЕрдиреБрдХреНрд░рдорд┐рдд рдЬреЗрдирд░рд┐рдХ"

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реЗ рдХреЛрдг рд╕реЗ рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдЧрд░ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рд▓рдВрдмрд╛ рдзрд╛рдЧрд╛ рд╣реИред рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЬреЗрдиреЗрд░рд┐рдХ рд╕реБрдЭрд╛рд╡ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛, рд╣рдо рдЗрдВрдбреЗрдХреНрд╕реЗрд╢рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЪреВрдВрдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓рд┐рдЯрд░рд▓реНрд╕ рдХреЛ рдЗрдВрдбреЗрдХреНрд╕рд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрдирдХрд╛ рд╕рдордХрдХреНрд╖ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ (рдЬреИрд╕рд╛ рдХрд┐ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдЗрд╕ рд╕рдордп рдирд╣реАрдВ рд╣реИрдВ):

interface A1 {
    a: number;
    b: boolean;
}
interface A2 {
    [index: "a"]: number;
    [index: "b"]: boolean;
}

рдЗрд╕рд▓рд┐рдП, рд╣рдо рддрдм рд▓рд┐рдЦ рд╕рдХрддреЗ рдереЗ

declare function pluck<P, T extends { [indexer: P]: R; }, R>(obj: T, p: P): R;

рдХреБрдЫ рдмрд╛рддреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

  • рдХреИрд╕реЗ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ рдХрд┐ P рдХреЗрд╡рд▓ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

    • рдЪреВрдВрдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ рд╕рднреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдлреИрд▓реА рд╣реБрдИ рд╣реИ, P extends string рдмрд╣реБрдд рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рдирд╣реАрдВ рд╣реЛрдЧреА

    • рдЕрдиреНрдп рдЪрд░реНрдЪрд╛ P super string рдмрд╛рдзрд╛ (# 7265, # 6613, https://github.com/Microsoft/TypeScript/issues/6613#issuecomment-175314703) рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реЛ рд░рд╣реА рд╣реИ

    • рдХреНрдпрд╛ рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдкрд░рд╡рд╛рд╣ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ? рд╣рдо рдЗрдВрдбреЗрдХреНрд╕рд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХреБрдЫ рднреА рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ рдЙрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рдпрджрд┐ T рдореЗрдВ string s рдпрд╛ number s рдХрд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рд╣реИред рддрдм P string рдпрд╛ number ред

  • рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдпрджрд┐ рд╣рдо рджреВрд╕рд░реЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ "something" рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ string рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрдЧрд╛

    • рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ # 10195 рдЙрддреНрддрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ

    • рдпрд╛ рдЯреАрдПрд╕ рдпрд╣ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реЛрдиреЗ рдкрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ P рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП

  • рдЗрдВрдбреЗрдХреНрд╕рд░реНрд╕ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╡реИрдХрд▓реНрдкрд┐рдХ { [i: string]: number /* | undefined */ }

    • рдЕрдЧрд░ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбреЛрдореЗрди рдореЗрдВ undefined рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВ?

  • P , T рдФрд░ R рдХреЗ рдмреАрдЪ рд╕рднреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд╖реНрдХрд░реНрд╖ рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреБрдВрдЬреА рд╣реИ

@weswigham @mhegazy , рдФрд░ рдореИрдВ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЗрд╕ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ; рд╣рдо рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЪрд▓рд╛рдП рдЬрд╛ рд░рд╣реЗ рдХрд┐рд╕реА рднреА рдШрдЯрдирд╛рдХреНрд░рдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдПрдВрдЧреЗ, рдФрд░ рдпрд╣ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рд╡рд┐рдЪрд╛рд░ рдХрд╛ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╣реИред

рд╡рд░реНрддрдорд╛рди рд╡рд┐рдЪрд╛рд░:

  • рдПрдХ keysof Foo рдСрдкрд░реЗрдЯрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ Foo рд╕реЗ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдореЛрдВ рдХреА рдпреВрдирд┐рдпрди рдХреЛ рд╣рдерд┐рдпрд╛рдиреЗ рдХреЗ рд▓рд┐рдПред
  • Foo[K] рдкреНрд░рдХрд╛рд░ рдЬреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ K рд▓рд┐рдП рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдорд┐рд▓рди рд╣реИред

рдЗрди рдмреБрдирд┐рдпрд╛рджреА рдмреНрд▓реЙрдХреЛрдВ рд╕реЗ, рдпрджрд┐ рдЖрдкрдХреЛ рдЙрдкрдпреБрдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

function foo<T, K extends keysof T>(obj: T, key: K): T[K] {
    // ...
}

рдпрд╣рд╛рдВ, K keysof T рдХрд╛ рдПрдХ рдЙрдкрдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдПрдХ рд╕рдВрдШ рд╣реИред рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ key рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХреБрдЫ рднреА рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрд╕реЗ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдЙрд╕ рд╢рд╛рдмреНрджрд┐рдХ / рд╢рд╛рдмреНрджрд┐рдХ рд╕рдВрдШ рджреНрд╡рд╛рд░рд╛ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдПрдХ рд╕рд┐рдВрдЧрд▓рдЯрди рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

interface HelloWorld { hello: any; world: any; }

function foo<K extends keysof HelloWorld>(key: K): K {
    return key;
}

// 'x' has type '"hello"'
let x = foo("hello");

рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ keysof рдЕрдХреНрд╕рд░ рдЗрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдореЗрдВ "рджреЗрд░реА" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЙрддреНрд╕реБрдХ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдореИрдВрдиреЗ рдЬреЛ рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдерд╛ (рдпрд╛рдиреА рдЬрд┐рд╕ рдорд╛рдорд▓реЗ рдХреЛ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рд╡рд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрдард┐рди рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ: рдореБрд╕реНрдХрд╛рди :)ред

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рд╕рднреА рдХреЛ рдПрдХ рдЕрджреНрдпрддрди рджреЗрддрд╛ рд╣реИред

@DanielRosenwasser рдЕрдкрдбреЗрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВрдиреЗ рдЕрднреА рджреЗрдЦрд╛ @weswigham рдиреЗ keysof рдСрдкрд░реЗрдЯрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ PR рд╕рдмрдорд┐рдЯ рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рд╢рд╛рдпрдж рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЖрдк рд▓реЛрдЧреЛрдВ рдХреЛ рд╕реМрдВрдкрдирд╛ рдмреЗрд╣рддрд░ рд╣реИред

рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдореВрд▓ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реЗ рдкреНрд░рд╕реНрдерд╛рди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рдХреНрдпреЛрдВ рд▓рд┐рдпрд╛?

function get(prop: string): T[prop];

рдФрд░ keysof рдкрд░рд┐рдЪрдп

T[prop] рдХрдо рд╕рд╛рдорд╛рдиреНрдп рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЗрдВрдЯрд░рд▓реЗрдХреНрдЯреЗрдб рдорд╢реАрдирд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдПрдХ рдмрдбрд╝рд╛ рд╕рд╡рд╛рд▓ рдпрд╣рд╛рдБ рдХреИрд╕реЗ рдЖрдк рднреА рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рд╕рд╛рдордЧреНрд░реА рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реЛрддрд╛ рд╣реИ prop рдХреА рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдирд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП T ред рдореБрдЭреЗ рднреА рдкреВрд░рд╛ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдк рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗред рдХреНрдпрд╛ рдЖрдк рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдкреНрд░рдХрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝реЗрдВрдЧреЗ? рдХреНрдпрд╛ рдЖрдкрдХреЛ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ рд╡реНрдпрд╡рд╣рд╛рд░ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА? рдХреНрдпрд╛ рдЖрдкрдХреЛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░реЛрдВ рдореЗрдВ рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛?

рдЬрд╡рд╛рдм рд╢рд╛рдпрдж рдЙрди рд╕рднреА рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рд╣рд╛рдБ рд╣реИред рдореИрдВрдиреЗ рд╣рдореЗрдВ рдЙрд╕рд╕реЗ рджреВрд░ рдХрд░ рджрд┐рдпрд╛ рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░реА рдЖрдВрдд рдиреЗ рдореБрдЭреЗ рдмрддрд╛рдпрд╛ рдХрд┐ рджреЛ рд╕рд░рд▓, рдЕрд▓рдЧ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдФрд░ рд╡рд╣рд╛рдВ рд╕реЗ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рдерд╛ред рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рд╣реИред

рдпрджрд┐ рдирдП рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВ рдЬреЛ рдЗрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рдХрд┐ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдЙрдирдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд▓рд┐рдЦрдирд╛ рдХрдард┐рди рдмрдирд╛ рд░рд╣рд╛ рд╣реИ, рддреЛ рд╢рд╛рдпрдж рд╣рдореЗрдВ рдЙрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЙрдкрднреЛрдХреНрддрд╛рдУрдВ рдХреА рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдкрдпреЛрдЧ-рд╕реНрдерд▓ рд╡рд╣ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдкрдХреЛ рд╡реИрд╕реЗ рднреА рд▓рд╛рдн рдорд┐рд▓рддрд╛ рд╣реИред

@DanielRosenwasser рдмрдореБрд╢реНрдХрд┐рд▓ рдЦрд░рдЧреЛрд╢ рдЫреЗрдж рдиреАрдЪреЗ рдЪрд▓рд╛ рдЧрдпрд╛ред рдореБрдЭреЗ рдЕрднреА рднреА @SaschaNaz рд╡рд┐рдЪрд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ keysof рдмреЗрдорд╛рдиреА рд╣реИред T[p] рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ рдХрд┐ p рдХреЛ T рдХреЗ рд╢рд╛рдмреНрджрд┐рдХ рд░рдВрдЧрдордВрдЪ рдХреА рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рд╕реЗ рдПрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореЗрд░рд╛ рдЦреБрд░рджрд░рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЛрдЪрд╛ рдерд╛ рдХрд┐ PropertyReferencedType рдирд╛рдордХ рдПрдХ рдирдП рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкрд░рд┐рдЪрдп рджрд┐рдпрд╛ рдЬрд╛рдПред

export interface PropertyReferencedType extends Type {
        property: Symbol;
        targetType: ObjectType;
}

рдЬрдм рдПрдХ рд╕рдорд╛рд░реЛрд╣ рдХреА рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рд╣реИ рдХрд┐ рдХреЗ рд╕рд╛рде рдШреЛрд╖рд┐рдд рдореЗрдВ рдкреНрд░рд╡реЗрд╢ PropertyReferencedType рдпрд╛ рдПрдХ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд┐ рд╕рдВрджрд░реНрдн PropertyReferencedType : рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ ElementAccessExpression рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд╕рд╛рде рд╕рдВрд╡рд░реНрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рд╕рдВрджрд░реНрдн рдкрд╣реБрдВрдЪ рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдкреНрд░рддреАрдХред

export interface Type {
        flags: TypeFlags;                // Flags
        /* <strong i="20">@internal</strong> */ id: number;      // Unique ID
        //...
        referencedProperty: Symbol; // referenced property
}

рддреЛ рдПрдХ рд╕рдВрджрд░реНрднрд┐рдд рд╕рдВрдкрддреНрддрд┐ рдкреНрд░рддреАрдХ рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХрд╛рд░ PropertyReferencedType ред рдЬрд╛рдБрдЪ рдХреЗ рджреМрд░рд╛рди, referencedProperty рдХреЛ p T[p] рдЕрдиреБрд░реВрдк рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдореВрд▓ рддрддреНрд╡ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ T рд▓рд┐рдП рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рдЪреАрдЬреЛрдВ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП p рдХреЛ рднреА const рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдирдпрд╛ рдкреНрд░рдХрд╛рд░ PropertyReferencedType рдХреЗрд╡рд▓ "рдЕрдирд╕реБрд▓рдЭреЗ рдкреНрд░рдХрд╛рд░" рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдореМрдЬреВрдж рд╣реИред рдХреЙрд▓ рд╕рд╛рдЗрдЯ рдкрд░ рдХрд┐рд╕реА рдХреЛ p рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

interface A { a: string }
declare function getProp(p: string): A[p]
getProp('a'); // string

PropertyReferencedType рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдЪрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдХреЙрд▓ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐ PropertyReferencedType рдХреЗрд╡рд▓ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬреЛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ T[p] рд╕рд╛рде рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╢рд░реАрд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред

рдпрджрд┐ рдЖрдк keysof рдФрд░ T[K] рдкреНрд░рдХрд╛рд░ рдХреЗ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдХреНрдпрд╛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдЙрдирдХрд╛ рдЗрд╕ рддрд░рд╣ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

interface A {
  a: number;
  b: string;
}
type AK = keysof A; // "a" | "b"
type AV = A[AK]; // number | string ?
type AA = A["a"]; // number ?
type AB = A["b"]; // string ?
type AC = A["c"]; // error?
type AN = A[number]; // error?

type X1 = keysof { [index: string]: number; }; // string ?
type X2 = keysof { [index: string]: number; [index: number]: string; }; // string | number ?

@DanielRosenwasser рдЖрдкрдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдореЗрд░реЗ рд╕рд╛рде рд╕рдорд╛рди рдЕрд░реНрде рдирд╣реАрдВ рд╣реЛрдЧрд╛

function foo<T, K extends keysof T>(obj: T, key: K): T[K] {
    // ...
}
// same as ?
function foo<K, V, T extends { [k: K]: V; }>(obj: T, key: K): V {
    // ...
}

рдореИрдВ рдпрд╣ рдирд╣реАрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рдХреЗ _.pick рдХреЗ рд▓рд┐рдП рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреИрд╕реЗ рд▓рд┐рдЦреЗ рдЬрд╛рдПрдВрдЧреЗ:

o2 = _.pick(o1, 'p1', 'p2');

pick(Object, ...props: String[]) : WHAT GOES HERE;

@rtm рдореИрдВрдиреЗ рдЗрд╕реЗ https://github.com/Microsoft/TypeScript/issues/1295#issuecomment -234724380 рдореЗрдВ рд╕реБрдЭрд╛рдпрд╛ рд╣реИред рдпрджреНрдпрдкрд┐ рдпрд╣ рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрд╣рддрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдпрд╣ рдЗрд╕ рдПрдХ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реЛред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЕрдм # 11929 рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

Roam-Cooper picture Roam-Cooper  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

DanielRosenwasser picture DanielRosenwasser  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

weswigham picture weswigham  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

fwanicka picture fwanicka  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

manekinekko picture manekinekko  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ