File tree Expand file tree Collapse file tree 4 files changed +83
-14
lines changed Expand file tree Collapse file tree 4 files changed +83
-14
lines changed Original file line number Diff line number Diff line change @@ -266,7 +266,9 @@ expectType<string>(
266266//// Select
267267///////////////////
268268
269- const gender = "male"
269+ type Gender = "male" | "female"
270+ const gender = "male" as Gender // make the type less specific on purpose
271+
270272expectType < string > (
271273 select ( gender , {
272274 // todo: here is inconsistency between jsx macro and js.
@@ -280,6 +282,36 @@ expectType<string>(
280282 } )
281283)
282284
285+ expectType < string > (
286+ // @ts -expect-error: missing required property and other is not supplied
287+ select ( gender , {
288+ male : "he" ,
289+ } )
290+ )
291+
292+ expectType < string > (
293+ // missing required property is okay, if other is supplied as fallback
294+ select ( gender , {
295+ male : "he" ,
296+ other : "they" ,
297+ } )
298+ )
299+
300+ expectType < string > (
301+ select ( gender , {
302+ // @ts -expect-error extra properties are not allowed
303+ incorrect : "" ,
304+ } )
305+ )
306+
307+ expectType < string > (
308+ select ( gender , {
309+ // @ts -expect-error extra properties are not allowed even with other fallback
310+ incorrect : "" ,
311+ other : "they" ,
312+ } )
313+ )
314+
283315expectType < string > (
284316 // @ts -expect-error value could be strings only
285317 select ( 5 , {
Original file line number Diff line number Diff line change @@ -154,12 +154,21 @@ export function selectOrdinal(
154154 options : ChoiceOptions
155155) : string
156156
157- type SelectOptions = {
157+ type SelectOptionsExhaustive < T extends string = string > = {
158+ [ key in T ] : string
159+ }
160+
161+ type SelectOptionsNonExhaustive < T extends string = string > = {
158162 /** Catch-all option */
159163 other : string
160- [ matches : string ] : string
164+ } & {
165+ [ key in T ] ?: string
161166}
162167
168+ type SelectOptions < T extends string = string > =
169+ | SelectOptionsExhaustive < T >
170+ | SelectOptionsNonExhaustive < T >
171+
163172/**
164173 * Selects a translation based on a value
165174 *
@@ -180,9 +189,9 @@ type SelectOptions = {
180189 * @param value The key of choices to use
181190 * @param choices
182191 */
183- export function select (
184- value : string | LabeledExpression < string > ,
185- choices : SelectOptions
192+ export function select < T extends string = string > (
193+ value : T | LabeledExpression < T > ,
194+ choices : SelectOptions < T >
186195) : string
187196
188197/**
Original file line number Diff line number Diff line change @@ -11,7 +11,8 @@ import {
1111import React from "react"
1212import { ph } from "@lingui/core/macro"
1313
14- const gender = "male"
14+ type Gender = "male" | "female"
15+ const gender = "male" as Gender
1516const user = {
1617 name : "John" ,
1718}
@@ -126,8 +127,20 @@ m = (
126127// @ts -expect-error: `value` could be string only
127128m = < Select value = { 5 } other = { "string" } />
128129
129- // @ts -expect-error: `other` required
130- m = < Select value = { "male" } />
130+ // @ts -expect-error: `other` required unless exhaustive
131+ m = < Select value = { gender } />
132+
133+ // @ts -expect-error: `other` required unless exhaustive
134+ m = < Select value = { gender } _male = "..." />
135+
136+ // @ts -expect-error: `other` required unless exhaustive
137+ m = < Select value = { gender } _female = "..." />
138+
139+ // non-exhaustive okay if other is defined
140+ m = < Select value = { gender } _female = "..." other = "..." />
141+
142+ // exhaustive okay without other
143+ m = < Select value = { gender } _male = "..." _female = "..." />
131144
132145// @ts -expect-error: `value` required
133146m = < Select other = { "male" } />
Original file line number Diff line number Diff line change @@ -32,12 +32,25 @@ type PluralChoiceProps = {
3232 [ digit : `_${number } `] : ReactNode
3333} & CommonProps
3434
35- type SelectChoiceProps = {
36- value : string | LabeledExpression < string | number >
35+ type SelectChoiceOptionsExhaustive < T extends string = string > = {
36+ [ key in T as `_${key } `] : ReactNode
37+ }
38+
39+ type SelectChoiceOptionsNonExhaustive < T extends string = string > = {
3740 /** Catch-all option */
3841 other : ReactNode
39- [ option : `_${string } `] : ReactNode
40- } & CommonProps
42+ } & {
43+ [ key in T as `_${key } `] ?: ReactNode
44+ }
45+
46+ type SelectChoiceOptions < T extends string = string > =
47+ | SelectChoiceOptionsExhaustive < T >
48+ | SelectChoiceOptionsNonExhaustive < T >
49+
50+ type SelectChoiceProps < T extends string = string > = {
51+ value : T | LabeledExpression < T >
52+ } & SelectChoiceOptions < T > &
53+ CommonProps
4154
4255/**
4356 * Trans is the basic macro for static messages,
@@ -105,7 +118,9 @@ export const SelectOrdinal: VFC<PluralChoiceProps>
105118 * />
106119 * ```
107120 */
108- export const Select : VFC < SelectChoiceProps >
121+ export const Select : {
122+ < T extends string = string > ( props : SelectChoiceProps < T > ) : React . JSX . Element
123+ }
109124
110125declare function _t ( descriptor : MacroMessageDescriptor ) : string
111126declare function _t (
You can’t perform that action at this time.
0 commit comments