рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ: рд╡рд┐рд╢реНрд╡рд╕рдиреАрдпрддрд╛ рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдпрд╛ рдЕрдХрд░реНрдордгреНрдпрддрд╛

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

рд╣рдо рдмрдЧреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдЯреАрдПрд╕ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд
1,500 рдЦреБрд▓реЗ рдХреАрдбрд╝реЗ рд╣реИрдВ рдФрд░ 6,000 рдмрдВрдж ('рд╣реИ: рдореБрджреНрджрд╛ рд╣реИ: рдЦреБрд▓рд╛ рд▓реЗрдмрд▓: рдмрдЧ')ред

рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

  • рдЯреАрдПрд╕ рд╕рдЦреНрдд рдореЛрдб рдЪрд╛рд▓реВ рд╣реИ (рд╕рдордЭрддреЗ рд╣реБрдП рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрд╛ рд╣реИ)
  • рдмрд┐рдирд╛ рд╕реНрдкрд╖реНрдЯ "рдХреЛрдИ": "рдХрд┐рд╕реА рднреА", "рдСрдмреНрдЬреЗрдХреНрдЯ", "рдлрд╝рдВрдХреНрд╢рди", {[рдХреБрдВрдЬреА: рд╕реНрдЯреНрд░рд┐рдВрдЧ]: рдЕрдЬреНрдЮрд╛рдд}
  • рдмрд┐рдирд╛ "рдХрд┐рд╕реА рднреА": (noImplicitAny) рдирд┐рд╣рд┐рдд: рдмрд┐рдирд╛ рдЖрдпрд╛рдд рдХрд┐рдП рдЧрдП рдЖрдпрд╛рдд (рд╢реБрджреНрдз рдЬреЗрдПрд╕ рдлрд╛рдЗрд▓реЗрдВ), рдЧрд▓рдд рдкреНрд░рдХрд╛рд░ рдХреА рд╣рд╕реНрддрдХреНрд╖реЗрдк
  • рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЧрд▓рдд рдЕрдиреБрдорд╛рди рдХреЗ рдмрд┐рдирд╛: рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛, рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЯрд╛рдЗрдкрд┐рдВрдЧ

рд╕рд╛рдордЧреНрд░реА:

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

рдкрд░рд┐рдЪрдп


рдЬреЗрдПрд╕ рдореЗрдВ рджреЛ рдирдВрдмрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ? рдПрдХ рднреЛрд▓реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓реЗ рд▓реЛ

function sum(a, b) {
	return a + b;
}

рдЪрд▓реЛ `рд░рд╛рд╢рд┐ (2, 2) === 4` рдХреЗ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпрд╛ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рдиреЗ рд▓рдЧрддрд╛ рд╣реИ? рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВ, рдЬрдм рд╣рдо рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЗрдирдкреБрдЯ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рдЪрд╛рд╣рд┐рдП, рд╕рд╛рде рд╣реА рдлрд╝рдВрдХреНрд╢рди рдХреНрдпрд╛ рд╡рд╛рдкрд╕ рдЖ рд╕рдХрддрд╛ рд╣реИ

1.1 + 2.7   // 3.8000000000000003
NaN + 2     // NaN
99999999999999992 + 99999999999999992 // 200000000000000000
2n + 2      // Uncaught TypeError: 
            // Cannot mix BigInt and other types, use explicit conversions.
{} + true   // 1
2 + '2'     // '22'

рд╕рд╛рдЙрдВрдбрдиреЗрд╕, рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреА рдпрд╣ рд╕рд╛рдмрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдЪрд▓рдиреЗ рдХреЗ рджреМрд░рд╛рди рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рджреНрд╡рд╛рд░рд╛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдпрд╣ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реЛрдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рд╣реИред

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

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

рдкреНрд░рдХрд╛рд░ рдпрд╣ рд╕рд╛рдмрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдкреВрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ, рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ рдФрд░ рдХреЗрд╡рд▓ рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ (100% рдХрд╡рд░реЗрдЬ, рд╕реНрдЯреНрд░рд╛рдЗрдХрд░ рд╕реЗ "рдореНрдпреВрдЯреЗрдВрдЯ" рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐, рд╕рдВрдкрддреНрддрд┐ рдЖрдзрд╛рд░рд┐рдд рдкрд░реАрдХреНрд╖рд╛ рдкрд╛рд╕ рдХрд░рдирд╛ рдФрд░ рдЗрддрдиреЗ рдкрд░ рдФрд░ рдХреБрдЫ рднреА рд╕рд╛рдмрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ) рдЬреЛрдЦрд┐рдо рдХрдо рдХрд░рддрд╛ рд╣реИ)ред рдРрд╕реА рдХрд┐рдВрд╡рджрдВрддрд┐рдпрд╛рдБ рд╣реИрдВ рдЬреЛ рдкреНрд░рдореЗрдп рд╕рд┐рджреНрдз рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╢реБрджреНрдзрддрд╛ рд╕рд╛рдмрд┐рдд рдХрд░ рд╕рдХрддреА рд╣реИрдВред

рдЯреАрдПрд╕ рджрд░реНрд╢рди рдХреЛ рд╕рдордЭрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╕рд╛рдзрди рдХреНрдпрд╛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдХреНрдпрд╛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред

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

рдбрд┐рдЬрд╝рд╛рдЗрди рд▓рдХреНрд╖реНрдп
рдЯреАрдПрд╕ рдХреЗ рд▓рд┐рдП рд▓рдХреНрд╖реНрдп рдирд╣реАрдВ - рд╕реБрд░рдХреНрд╖рд╛ рдХреА рдЧрд╛рд░рдВрдЯреА рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рд╕реБрд░рдХреНрд╖рд╛ рдФрд░ рдЙрддреНрдкрд╛рджрдХрддрд╛ рдХреЗ рдмреАрдЪ рд╕рдВрддреБрд▓рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ

рдЙрджрд╛рд╣рд░рдг рд╕рдВрд░рдЪрдирд╛:
рд╕рдорд╕реНрдпрд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдирд╣реАрдВ рд╣реИ, рд╕реВрдЪреА рдкреВрд░реА рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рд▓реЗрдЦреЛрдВ, рд░рд┐рдкреЛрд░реНрдЯреЛрдВ рдореЗрдВ рдкрд╛рдпрд╛ рд╣реИ, рдЯреАрдПрд╕ рдЧрд┐рдЯ рдореБрджреНрджреЛрдВред
рдкреНрд░рд╕реНрддрд╛рд╡ 3-4 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдЦреБрд▓рд╛ рдПрдХ рдЯреАрдПрд╕ рдореБрджреНрджрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд▓реЗрдЦрдХреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рд╕реНрдкрд╖реНрдЯреАрдХрд░рдгреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рд╣реИред
рдЯрд┐рдк - рд▓реЗрдЦрдХ рдХрд╛ рдЖрдИрдПрдордПрдЪрдУ, рд▓реЗрдЦрдХ рдЕрдЪреНрдЫреА рдкреНрд░рдерд╛рдУрдВ рдХреЛ рдХреНрдпрд╛ рдорд╛рдирддрд╛ рд╣реИ

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ


рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 1. рд╕рдорд╕реНрдпрд╛


рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдЯрд╛рдЗрдкрд┐рдВрдЧ - рдЬрдм рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рддреБрд▓рдирд╛ рдЙрдирдХреЗ рдирд╛рдо рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ рдпрд╛ рдЬрд╣рд╛рдВ рд╡реЗ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЧрдП рдереЗ, рдФрд░ рдкреНрд░рдХрд╛рд░ рдХреА рддреБрд▓рдирд╛ "рд╕рдВрд░рдЪрдирд╛" рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреА рдЬрд╛рддреА рд╣реИред

рд╣рдо рдкрддреНрд░ `sendEmail` рдХреЛ рд╕рд╣реА рдкрддреЗ рдкрд░ рднреЗрдЬрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ` ValidatedEmail`, рдкрддрд╛ `рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛` рдХреА рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рд╕рд╣реА рдкрддрд╛` ValidatedEmail` рджреЗрддрд╛ рд╣реИред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдЯреАрдПрд╕ рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ `рд╕реЗрдВрдбрдЗрдореЗрд▓` рднреЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ TS рдХреЗ рд▓рд┐рдП `ValidatedEmail`` string` рд╕реЗ рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИ

type ValidatedEmail = string;
declare function validateEmail(email: string): ValidatedEmail;

declare function sendEmail(mail: ValidatedEmail): void;
sendEmail(validateEmail("asdf@gmail.com"));

// Should be error!
sendEmail("asdf@gmail.com");

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 1. рдкреНрд░рд╕реНрддрд╛рд╡


github.com/microsoft/TypeScript/issues/202
рдХреАрд╡рд░реНрдб рджрд░реНрдЬ рдХрд░реЗрдВ `рдирд╛рдордорд╛рддреНрд░` рддрд╛рдХрд┐ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рдПред рдЕрдм рд╣рдо рдХреЗрд╡рд▓ 'рд╕реНрдЯреНрд░рд┐рдВрдЧ' рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдкрд░ рд░реЛрдХ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ `рд╡реИрдзреАрдХреГрдд 'рдИрдореЗрд▓ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ

nominal type ValidatedEmail = string;
declare function validateEmail(email: string): ValidatedEmail;

declare function sendEmail(mail: ValidatedEmail): void;
sendEmail(validateEmail('asdf@gmail.com'));

// Error!
sendEmail('asdf@gmail.com');

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 1. рдЯрд┐рдк


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

type Opaque<K extends symbol | string, T> 
	= T & { [X in K]: never };

declare const validatedEmailK: unique symbol;
type ValidatedEmail = Opaque<typeof validatedEmailK, string>;
// type ValidatedEmail = Opaque<'ValidatedEmail', string>;

declare function validateEmail(email: string): ValidatedEmail;

declare function sendEmail(mail: ValidatedEmail): void;
sendEmail(validateEmail('asdf@gmail.com'));

// Argument of type '"asdf@gmail.com"' is not assignable
//  to parameter of type 'Opaque<unique symbol, string>'.
sendEmail('asdf@gmail.com');

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 2. рд╕рдорд╕реНрдпрд╛


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

export class Dollar {
  value: number;

  constructor(value: number) {
    this.value = value;
  }

  add(dollar: Dollar): Dollar {
    return new Dollar(dollar.value + this.value);
  }
}

class Euro {
  value: number;

  constructor(value: number) {
    this.value = value;
  }

  add(euro: Euro): Euro {
    return new Euro(euro.value + this.value);
  }
}

const dollars100 = new Dollar(100);
const euro100 = new Euro(100);

// Correct
dollars100.add(dollars100);
euro100.add(euro100);

// Should be error!
dollars100.add(euro100);

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 2. рдкреНрд░рд╕реНрддрд╛рд╡


github.com/microsoft/TypeScript/issues/202
рд╡рд╛рдХреНрдп рд╕рднреА рд╕рдорд╛рди рд╣реИ, `рдирд╛рдордорд╛рддреНрд░` рдХреЗ рд╕рд╛рде, рд▓реЗрдХрд┐рди рддрдм рд╕реЗ рдЪреВрдВрдХрд┐ рдХрдХреНрд╖рд╛рдПрдВ рдЬрд╛рджреБрдИ рд░реВрдк рд╕реЗ рдирд╛рдордорд╛рддреНрд░ рдмрди рд╕рдХрддреА рд╣реИрдВ (рдмрд╛рдж рдореЗрдВ рдЙрд╕ рдкрд░ рдЕрдзрд┐рдХ), рдРрд╕реЗ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдмрдирд╛рдо рдирд╛рдордорд╛рддреНрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ 1. рдЯрд┐рдк


рдпрджрд┐ рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░ рд╣реИ (рдореВрд▓ рд░реВрдк рд╕реЗ `#` рдпрд╛ TS c `рдирд┐рдЬреА` рд╕реЗ), рддреЛ рд╡рд░реНрдЧ рдЬрд╛рджреБрдИ рд░реВрдк рд╕реЗ рдирд╛рдордорд╛рддреНрд░ рдХрд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдирд╛рдо рдФрд░ рдореВрд▓реНрдп рдХреБрдЫ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред `! (рдирд┐рд╢реНрдЪрд┐рдд рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдЕрд╕реЗрд╕рдореЗрдВрдЯ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдЯреАрдПрд╕ рдХреЛ рдПрдХ рдЕрд╕рд┐рдВрдЪрд┐рдд рдХреНрд╖реЗрддреНрд░ рдкрд░ рд╢рдкрде рдЧреНрд░рд╣рдг рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд╕рдЦреНрддNullChecks, рд╕рдЦреНрддPropertyInitialization рдзреНрд╡рдЬ рд╕рдХреНрд╖рдо рд╣реИрдВ)ред

class Dollar {
  // #desc!: never;
  private desc!: never;
  value: number;

  constructor(value: number) {
    this.value = value;
  }

  add(dollar: Dollar) {
    return new Dollar(dollar.value + this.value);
  }
}

class Euro {
  // #desc!: never;
  private desc!: never;
  value: number;

  constructor(value: number) {
    this.value = value;
  }

  add(euro: Euro) {
    return new Euro(euro.value + this.value);
  }
}

const dollars100 = new Dollar(100);
const euro100 = new Euro(100);

// Correct
dollars100.add(dollars100);
euro100.add(euro100);

// Error: Argument of type 'Euro' is not assignable to parameter of type 'Dollar
dollars100.add(euro100);

рдкреНрд░рдХрд╛рд░ рднрд┐рдиреНрдирддрд╛ 1. рд╕рдорд╕реНрдпрд╛


рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╡рд┐рдХрд▓реНрдк, рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рд╡рд╣рд╛рдВ рд╕реБрдкрд░рдЯрд╛рдЗрдк / рд╕рдмрдЯрд╛рдЗрдк рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдЯрд╛рдЗрдк рдХреА рдЙрдореНрдореАрдж рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдкрджрд╛рдиреБрдХреНрд░рдо рдЖрдХреГрддрд┐ рд╣реИ -> рд╕рд░реНрдХрд▓ -> рдЖрдпрдд, рдХреНрдпрд╛ рд╕рд░реНрдХрд▓ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХреА рдЬрд╛рддреА рд╣реИ рддреЛ рдХрд┐рд╕реА рдЖрдХреГрддрд┐ / рдЖрдпрдд рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ?

рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╣рдмреНрд░ рдореЗрдВ рд╡реЗрд░рд┐рдПрдВрдЯ , рдПрд╕рдУ ред

рд╣рдо рдЙрд╕ рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рдкреНрд░рдХрд╛рд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╕рдВрдЦреНрдпрд╛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдирд┐рд╣рд┐рдд рд╣реЛрддреА рд╣реИ рдЬреЛ рдлрд╝реАрд▓реНрдб рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдпрд╛ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреА рд╣реИ, рдФрд░ рд╢рд░реАрд░ рдореЗрдВ рд╕рдВрдЪрд░рд┐рдд рд╡рд╕реНрддреБ рдХреЛ рдмрджрд▓ рджреЗрддреА рд╣реИ, рдлрд╝реАрд▓реНрдб рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓ рджреЗрддреА рд╣реИред рдЙрдиред `{рд╕реНрдерд┐рддрд┐: рд╕рдВрдЦреНрдпрд╛} рдХреЗ рд░реВрдк рдореЗрдВ {рд╕реНрдерд┐рддрд┐: рд╕рдВрдЦреНрдпрд╛ | string} as {status: string} `рдпрд╣рд╛рдВ рдПрдХ рдРрд╕реА рдЯреНрд░рд┐рдХ рд╣реИ, рдЬреЛ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓ рджреЗрддреА рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдПрдХ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИред

function changeStatus(arg: { status: number | string }) {
  arg.status = "NotFound";
}

const error: { status: number } = { status: 404 };
changeStatus(error);

// Error: toFixed is not a function
console.log(error.status.toFixed());

рдкреНрд░рдХрд╛рд░ рднрд┐рдиреНрдирддрд╛ 1. рдкреНрд░рд╕реНрддрд╛рд╡


github.com/Microsoft/TypeScript/issues/10717
рдЬреЗрдирд░рд┐рдХ рдХреЗ рд▓рд┐рдП рд╕рд╣-рдкреНрд░рдЪрд╛рд░ / рд╡рд┐рд░реЛрдзрд╛рднрд╛рд╕реА рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП `рдХреЛ` рдореЗрдВ `` рд╢реБрд░реВ рдХрд░рдирд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╣реИред

function changeStatus<
  out T extends {
    status: number | string;
  }
>(arg: T) {
  arg.status = "NotFound";
}

const error: { status: number } = { status: 404 };
// Error!
changeStatus(error);

console.log(error.status.toFixed());

рдкреНрд░рдХрд╛рд░ рд╡рд┐рдЪрд░рдг 1. рдЯрд┐рдк


рдпрджрд┐ рд╣рдо рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдРрд╕реА рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реЛрдЧреА (рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдЦреНрдд рдлрд╝рд╛рдЗрдирд▓реАрдкреНрдЯреНрд╕ рдзреНрд╡рдЬ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ)ред

function changeStatus(arg: Readonly<{ status: number | string }>) {
  // Error: Cannot assign, status is not writable
  arg.status = "NotFound";
}

const error: Readonly<{ status: number }> = { status: 404 };
changeStatus(error);

console.log(error.status.toFixed());

рдкреНрд░рдХрд╛рд░ рд╡рд┐рдЪрд░рдг 1. рдмреЛрдирд╕


рдкрдардиреАрдп рд░реВрдк рд╕реЗ рдкрдардиреАрдп
github.com/Microsoft/TypeScript/issues/13347
github.com/microsoft/TypeScript/pull/6532#issuecomment-174356151

рдкрд░ рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ , рд▓реЗрдХрд┐рди рдпрджрд┐ рд╣рдо Readonly рдкреНрд░рдХрд╛рд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ TS рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордирд╛ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдЬрд╣рд╛рдВ рдЕрдкреЗрдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ Readonly `Readonly <{readonly status: number}> as {status: number | string} as {status: string} `

function changeStatus(arg: { status: number | string }) {
  arg.status = "NotFound";
}

const error: Readonly<{ readonly status: number }> 
  = { status: 404 };
changeStatus(error);

// Error: toFixed is not a function
console.log(error.status.toFixed());

рдкреНрд░рдХрд╛рд░ рднрд┐рдиреНрдирддрд╛ 2. рд╕рдорд╕реНрдпрд╛


рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдирдХреЗ рдкреНрд░рдХрд╛рд░ рдЙрдирдХреЗ рдкрд╛рд╕ рдирд╣реАрдВ рд╣реИрдВ: `{рд╕рдВрджреЗрд╢: рд╕реНрдЯреНрд░рд┐рдВрдЧ; рд╕реНрдерд┐рддрд┐: рд╕реНрдЯреНрд░рд┐рдВрдЧ} рдХреЗ рд░реВрдк рдореЗрдВ {рд╕рдВрджреЗрд╢: рд╕реНрдЯреНрд░рд┐рдВрдЧ} `ред рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рдХреБрдЫ рдСрдкрд░реЗрд╢рди рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ

const error: { message: string; status: string } = {
  message: "No data",
  status: "NotFound"
};

function updateError(arg: { message: string }) {
  const defaultError = { message: "Not found", status: 404 };
  const newError: { message: string; status: number }
    = { ...defaultError, ...arg };
  
  // Error: toFixed is not a function
  console.log(newError.status.toFixed());
}

updateError(error);

рдЯреАрдПрд╕ рдиреЗ рд╕реЛрдЪрд╛ рдХрд┐ рдорд░реНрдЬ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, `{... {рд╕рдВрджреЗрд╢: рд╕реНрдЯреНрд░рд┐рдВрдЧ, рд╕реНрдерд┐рддрд┐: рд╕рдВрдЦреНрдпрд╛}, ... {рд╕рдВрджреЗрд╢: рд╕реНрдЯреНрд░рд┐рдВрдЧ}}` рд╕реНрдерд┐рддрд┐ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рд╣реЛрдЧреАред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, `{... {рд╕рдВрджреЗрд╢:" рдирд╣реАрдВ рдорд┐рд▓рд╛ ", рд╕реНрдерд┐рддрд┐: 404}, ... {рд╕рдВрджреЗрд╢:" рдХреЛрдИ рдбреЗрдЯрд╛ рдирд╣реАрдВ ", рд╕реНрдерд┐рддрд┐:" NotFound "},}` рд╕реНрдерд┐рддрд┐ - рд╕реНрдЯреНрд░рд┐рдВрдЧред

рдкреНрд░рдХрд╛рд░ рднрд┐рдиреНрдирддрд╛ 2. рдкреНрд░рд╕реНрддрд╛рд╡


github.com/microsoft/TypeScript/issues/12936
рдПрдХ `рд╕рдЯреАрдХ` рдкреНрд░рдХрд╛рд░ рдпрд╛ рд╕рдорд╛рди рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реБрдП рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝реАрд▓реНрдб рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗред

const error: Exact<{ message: string; }> = {
  message: "No data",
};

function updateError(arg: Exact<{ message: string }>) {
  const defaultError = {  message: "Not found", status: 404, };
  // Can spread only Exact type!
  const newError = { ...defaultError, ...arg };
  console.log(newError.status.toFixed());
}

updateError(error);

рдкреНрд░рдХрд╛рд░ рднрд┐рдиреНрдирддрд╛ 2. рдпреБрдХреНрддрд┐


рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдиреЗ рдпрд╛ рдЕрдЬреНрдЮрд╛рдд рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдорд░реНрдЬ рдХрд░реЗрдВред

const error: { message: string; status: string } = {
  message: "No data",
  status: "NotFound"
};

function updateError(arg: { message: string }) {
  const defaultError = { message: "Not found", status: 404 };
  // Merge explicitly or filter unknown fields
  const newError = { ...defaultError, message: arg.message };
  console.log(newError.status.toFixed());
}

updateError(error);

рд╢реЛрдзрди рдЕрдорд╛рдиреНрдпред рдореБрд╕реАрдмрдд


рдмрд╛рд╣рд░реА рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рд╕рд╛рдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рдмрд╛рд╣рд░реА рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд╣реАрдВ рдмрджрд▓рддреЗ рд╣реИрдВ:

export function logAge(name: string, age: number) {
  // 2nd call -  Error: toFixed is not a function
  console.log(`${name} will lose ${age.toFixed()}`);
  person.age = "PLACEHOLDER";
}

const person: { name: string; age: number | string } = {
  name: "Person",
  age: 42
};

if (typeof person.age === "number") {
  logAge(person.name, person.age);
  // refinement should be invalidated
  logAge(person.name, person.age);
}

рд╢реЛрдзрди рдЕрдорд╛рдиреНрдпред рд╡рд╛рдХреНрдп


github.com/microsoft/TypeScript/issues/7770#issuecomment-334919251
рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рд▓рд┐рдП `рд╢реБрджреНрдз` рд╕рдВрд╢реЛрдзрдХ рдЬреЛрдбрд╝реЗрдВ, рдпрд╣ рдХрдо рд╕реЗ рдХрдо рдЖрдкрдХреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛

рд╢реЛрдзрди рдЕрдорд╛рдиреНрдпред рдЯрд┐рдк


рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдлрд┐рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдкрд┐рдЫрд▓реЗ рдЪреЗрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реЛрдЧреАред

рдмрдХреНрд╢реАрд╢


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

рдЕрдкрд╡рд╛рджред рдореБрд╕реАрдмрдд


рдЯреАрдПрд╕ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдлрд╝рдВрдХреНрд╢рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкрд░ рдХреБрдЫ рднреА рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИред

import { JokeError } from "../helpers";

function getJoke(isFunny: boolean): string {
  if (isFunny) {
    throw new JokeError("No funny joke");
  }
  return "Duh";
}

const joke: string = getJoke(true);
console.log(joke);

рдЕрдкрд╡рд╛рджред рд╡рд╛рдХреНрдп


github.com/microsoft/TypeScript/issues/13219
рдпрд╣ рдПрдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдкреЗрд╢ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд╣реИ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ

import { JokeError } from '../helpers';

function getJoke(isFunny: boolean): string | throws JokeError {
  /*...*/}

function getJokeSafe(isFunny: boolean): string {
  try {
    return getJoke(isFunny);
  } catch (error) {
    if (error instanceof JokeError) {
      return "";
    } else {
      // Should infer error correctly, should cast to never
      return error as never;
    }
  }
}

console.log(getJokeSafe(true));

рдЕрдкрд╡рд╛рджред рдмрдХреНрд╢реАрд╢


github.com/microsoft/TypeScript/issues/6283
рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, TS рдореЗрдВ, Promise рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рддрд╛ рд╣реИ

const promise1: Promise<number> = Promise.resolve(42);

const promise: Promise<never> = Promise.reject(new TypeError());

// typescript/lib
interface PromiseConstructor {
  new <T>(
    executor: (
      resolve: (value?: T | PromiseLike<T>) => void,
      reject: (reason?: any) => void
    ) => void
  ): Promise<T>;
}

рдЕрдкрд╡рд╛рджред рдЯрд┐рдк


рдХреЗрд╡рд▓ рд╢реНрд░реЗрд╖реНрда рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде, рдкреНрд░реЙрдорд┐рд╕ рдЬреИрд╕рд╛ рдХреЛрдИ рднреА рдХрдВрдЯреЗрдирд░ рд▓реЗрдВред ( рдпрд╛ рддреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрджрд╛рд╣рд░рдг )

import { Either, exhaustiveCheck, JokeError } from "../helpers";

function getJoke(isFunny: boolean): Either<JokeError, string> {
  if (isFunny) {
    return Either.left(new JokeError("No funny joke"));
  }
  return Either.right("Duh");
}

getJoke(true)
  // (parameter) error: JokeError
  .mapLeft(error => {
    if (error instanceof JokeError) {
      console.log("JokeError");
    } else {
      exhaustiveCheck(error);
    }
  })
  // (parameter) joke: string
  .mapRight(joke => console.log(joke));

рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдВрдЪрд╛рд▓рдиред рдореБрд╕реАрдмрдд


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

// ReadOnly fixed size tuple
export const constNumbers: readonly [1, 2, 3] 
  = [1, 2, 3] as const;

// Error: Object is possibly 'undefined'.
console.log(constNumbers[100].toFixed());

const dynamicNumbers: number[] = [1, 2, 3];
console.log(dynamicNumbers[100].toFixed());

рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдВрдЪрд╛рд▓рдиред рд╡рд╛рдХреНрдп


github.com/microsoft/TypeScript/issues/13778
рдпрд╣ рд╕рд░рдгреА рдореЗрдВ рдЗрдВрдбреЗрдХреНрд╕ рдПрдХреНрд╕реЗрд╕ рдХреЗ рд▓рд┐рдП `рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд` рдХреЛ рд░рд┐рдЯрд░реНрди рдЯрд╛рдЗрдк` T` рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХрд┐рд╕реА рднреА рдЗрдВрдбреЗрдХреНрд╕ рдкрд░ рдкрд╣реБрдБрдЪрддреЗ рд╕рдордп, рдЖрдкрдХреЛ `?` рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдпрд╛ рд╕реНрдкрд╖реНрдЯ рдЬрд╛рдБрдЪ рдХрд░рдиреА рд╣реЛрдЧреАред

// interface Array<T> {
//   [n: number]: T | undefined;
// }

const dynamicNumbers: number[] = [1, 2, 3];
// Error: Object is possibly 'undefined'.
console.log(dynamicNumbers[100].toFixed());

// Optional chaining `?`
console.log(dynamicNumbers[100]?.toFixed());

// type refinement
if (typeof dynamicNumbers[100] === 'number') {
  console.log(dynamicNumbers[100].toFixed());
}

рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдВрдЪрд╛рд▓рдиред рдЯрд┐рдк


рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдкрд░реЗ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рдЬреНрдЮрд╛рдд рдХрдВрдЯреЗрдирд░ `рдПрдЕрд░`` рдХреЛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдЬреЛ` рдПрдЕрд░ <null, T> `рд▓реМрдЯрд╛рдПрдЧрд╛ред

import { Either } from "../helpers";

function safeIndex<T>(
  array: T[],
  index: number,
): Either<null, T> {
  if (index in array) {
    return Either.right(array[index]);
  }
  return Either.left(null);
}

const dynamicNumbers: number[] = [1, 2, 3];

safeIndex(dynamicNumbers, 100)
  .mapLeft(() => console.log("Nothing"))
  .mapRight(el => el + 2)
  .mapRight(el => console.log(el.toFixed()));

рдмрдХреНрд╢реАрд╢ рдкреБрдирдГ рд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп


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

PS рд╕рд╛рдорд╛рдиреНрдп рдФрд░ рд╕рд╢рд░реНрдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд┐рдХрд▓реНрдк рджреЗрдЦреЗрдВ:

function add(a: string, b: string): string;
function add(a: number, b: number): number;
function add(a: string | number,
             b: string | number,
): string | number {
  return `${a} + ${b}`;
}

const sum: number = add(2, 2);
// Error: toFixed is not a function
sum.toFixed();


рдмрдХреНрд╢реАрд╢ рдЧрд╛рд░реНрдб рдЯрд╛рдЗрдк рдХрд░реЗрдВ


рдЯреАрдПрд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ `рд╕реБрдкрд░рд╕реБрд╕рд░` рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐` рд╕реБрдкрд░рдпреВрдЬрд╝рд░` рдХреМрди рд╣реИ рдФрд░ рдпрджрд┐ `рд╡рд╛рд╕реНрдпрд╛` рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреЛрдИ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред

PS рдпрд╣ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ рдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдирдХреЗ рд╕рдВрдШ рдЯреИрдЧ рдХрд┐рдП рдЧрдП рд╕рдВрдШ рдХреЗ рд╕реНрддрд░ рдкрд░ рдХреИрд╕реЗ рднреЗрдж рдХрд░реЗрдВрдЧреЗ

type SimpleUser = { name: string };
type SuperUser = { 
  name: string; 
  isAdmin: true; 
  permissions: string[] 
};
type Vasya = { name: string; isAdmin: true; isGod: true };
type User = SimpleUser | SuperUser | Vasya;

function isSuperUser(user: User): user is SuperUser {
  return "isAdmin" in user && user.isAdmin;
}

function doSomethings(user: User) {
  // Error: Cannot read property 'join' of undefined
  if (isSuperUser(user)) {
    console.log(user.permissions.join(","));
  }
}

рдпреБрдХреНрддрд┐рдпреЛрдВ рдкрд░ рдирд┐рд╖реНрдХрд░реНрд╖


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

рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдбреЗрдЯрд╛, рд╢реБрджреНрдз рдХрд╛рд░реНрдп, рдорда ... рдмрдзрд╛рдИ , рд╣рдордиреЗ рд╕рд╛рдмрд┐рдд рдХрд┐рдпрд╛ рдХрд┐ рдПрдлрдкреА рд╢рд╛рдВрдд рд╣реИ!

рдЬрд╛рдБрдЪ - рдкрд░рд┐рдгрд╛рдо


  • рдЯреАрдПрд╕ рд╢реБрджреНрдзрддрд╛ рдФрд░ рдЙрддреНрдкрд╛рджрдХрддрд╛ рдХреЗ рдмреАрдЪ рд╕рдВрддреБрд▓рди рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ
  • рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рд╕реБрд░рдХреНрд╖рд╛ рдФрд░ рд╢реБрджреНрдзрддрд╛ рд╕рд╛рдмрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
  • рдкреНрд░рдХрд╛рд░ рдПрдХ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕рдордЧреНрд░ рд╕реБрд░рдХреНрд╖рд╛ рд╕рд╛рдмрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
  • рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди - рдмреБрд░рд╛, рдареАрдХ рд╣реИ?

рдЬреИрд╕рд╛ рдХрд┐ DZ рдлреНрд▓реЛ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рддреНрд░реБрдЯрд┐ рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

// https://flow.org/try/
declare function log(arg: { name: string, surname?: string }): void;
const person: { name: string } =  { name: 'Negasi' };
// Error
log(person);

рдЙрджрд╛рд╣рд░рдг рдХреЛрдб, рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг, рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ ред

All Articles