إصدار TypeScript: 3.0.3
مصطلحات البحث: اكتب بناءً على القيم الموجودة في المصفوفة
هل هناك ميزة حالية أو مخططة لإنشاء نوع من سلاسل في مصفوفة؟
الشفرة
const values = ['A', 'B']
type Foo = OneOf<values> // Is there a way of doing this?
const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values
على غرار كيفية عمل keyof
:
const values = {
A: 'A',
B: 'B'
}
type Foo = keyof typeof values
const v1: Foo = 'A'
const v2: Foo = 'D' // Type '"D"' is not assignable to type '"A" | "B"'
القضايا ذات الصلة:https://github.com/Microsoft/TypeScript/issues/20965
رابط إلى الملعب http://www.typescriptlang.org/play/#src = let٪ 20vals1٪ 20٪ 3D٪ 20٪ 5B'A '٪ 2C٪ 20'B'٪ 5D٪ 0D٪ 0Atype٪ 20Foo1٪ 20٪ 3D٪ 20OneOf٪ 3Cvals1٪ 3E٪ 20٪ 2F٪ 2F٪ 20Is٪ 20there٪ 20a٪ 20way٪ 20of٪ 20doing٪ 20this٪ 3F٪ 0D٪ 0A٪ 0D٪ 0Alet٪ 20v1٪ 3A٪ 20Foo1٪ 20٪ 3D٪ 20 ' A '٪ 20٪ 2F٪ 2F٪ 20This٪ 20should٪ 20work٪ 0D٪ 0Alet٪ 20v2٪ 3A٪ 20Foo1٪ 20٪ 3D٪ 20'D'٪ 20٪ 2F٪ 2F٪ 20 هذا٪ 20 يجب٪ 20 إعطاء٪ 20me٪ 20an٪ 20 خطأ٪ 20 منذ٪ 20'D '٪ 20 لا يوجد٪ 20 موجود٪ 20 في٪ 20 قيم٪ 0D٪ 0A٪ 0D٪ 0 منفذ٪ 20vals2٪ 20٪ 3D٪ 20٪ 7B٪ 0D٪ 0A٪ 20٪ 20A٪ 3A٪ 20'A '٪ 2C٪ 0D٪ 0A٪ 20٪ 20B٪ 3A٪ 20'B'٪ 0D٪ 0A٪ 7D٪ 0D٪ 0Atype٪ 20Foo2٪ 20٪ 3D٪ 20keyof٪ 20typeof٪ 20vals2٪ 0D٪ 0Alet٪ 20v3٪ 3A٪ 20Foo2 ٪ 20٪ 3D٪ 20'A '٪ 0D٪ 0Alet٪ 20v4٪ 3A٪ 20Foo2٪ 20٪ 3D٪ 20'D'٪ 20٪ 2F٪ 2F٪ 20Type٪ 20 '٪ 22D٪ 22'٪ 20is٪ 20not٪ 20 ٪ 20 to٪ 20type٪ 20 '٪ 22A٪ 22٪ 20٪ 7C٪ 20٪ 22B٪ 22'
keyof
يعمل فقط لأنه يستخدم معلومات معروفة بشكل ثابت في وقت الترجمة. الأنواع في TS قابلة للمسح بالكامل ولا توجد في الشفرة المنقولة ، لذلك لا يمكن ببساطة إنشاء نوع بناءً على محتويات وقت تشغيل المصفوفة.
هذا ممكن:
function stringLiterals<T extends string>(...args: T[]): T[] { return args; }
type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType> ? ElementType : never;
const values = stringLiterals('A', 'B');
type Foo = ElementType<typeof values>;
const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values
بالتأكيد ليس من الواضح كيفية القيام بذلك بالرغم من ذلك. # 27179 مرتبط.
هذا لا يزال يستخدم المعلومات المعروفة بشكل ثابت من قبل المترجم. في هذه المرحلة ، لا أفهم ما هي الميزة التي انتهت بمجرد قول ”A” | “B”
.
fatcerberus من المفيد تجنب تكرار المعلومات - إذا كتبت للتو const values = ["A", "B"]; type Foo = "A" | "B";
فمن السهل على شخص ما تغيير أحدهما بينما ينسى تغيير الآخر. يمكنك كتابة const values: Foo[] =["A", "B"];
، لكن هذا لا يزال عرضة لإضافة إدخال إضافي إلى Foo
ونسيان وضعه في values
.
أين نحن من هذا الآن؟
قال Like @ andy-ms أنه سيكون من المفيد حقًا تجنب تكرار المعلومات يدويًا.
ومثلما قال
بناءً على إجابة @ andy-ms ، وباستخدام تأكيدات const المقدمة في النسخة المطبوعة 3.4 ، أصبح من الممكن الآن القيام بشيء كهذا
const values = ['A', 'B'] as const
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
infer ElementType
>
? ElementType
: never
type Foo = ElementType<typeof values> // this is correctly inferred as literal "A" | "B"
تم وضع علامة "سؤال" على هذه المشكلة ولم تشهد أي نشاط حديثًا. تم إغلاقه تلقائيًا لأغراض التدبير المنزلي. إذا كنت لا تزال تنتظر ردًا ، فعادة ما تكون الأسئلة مناسبة بشكل أفضل لتدفق المكدس .
في [email protected] وما فوق. حلها هكذا
export const type = <const>[
'room',
'room_with_gifter',
'user_send'
];
export interface Activity {
id?: string;
type: typeof type[number];
}
بدلا من هذا:
export const items = <const>[
'room',
'room_with_gifter',
'user_send'
];
export interface Activity {
id?: string;
type: typeof items[number];
}
انت تستطيع فعل ذالك:
export const items = [
'room',
'room_with_gifter',
'user_send'
] as const;
export type Item = typeof items;
export interface Activity {
id?: string;
type: Item;
}
_ حقًا لا أحب استخدام type
كاسم متغير ._
@ 7kms
في [email protected] وما فوق. حلها هكذا
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
الآن ماذا لو كان لدي هذا في الفصل؟
class Class {
const list = <const>[
'room',
'room_with_gifter',
'user_send'
];
const withType: typeof list[number];
}
لا يعمل. أنا أيضًا لا أستطيع أن أفعل this.list[number]
. أيضا ، من أجل خاصتي
usecase ، لا يمكنني تعيين list
ليكون static
@ 7kms
في [email protected] وما فوق. حلها هكذا
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
الآن ماذا لو كان لدي هذا في الفصل؟
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
لا يعمل. أنا أيضًا لا أستطيع أن أفعل
this.list[number]
. أيضا ، من أجل خاصتي
usecase ، لا يمكنني تعيينlist
ليكونstatic
vegerot لا يمكنك استخدام const
مباشرة في نطاق class
، لذا فإن البنية غير صحيحة.
@ 7kms
في [email protected] وما فوق. حلها هكذا
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
الآن ماذا لو كان لدي هذا في الفصل؟
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
لا يعمل. أنا أيضًا لا أستطيع أن أفعل
this.list[number]
. أيضا ، من أجل خاصتي
usecase ، لا يمكنني تعيينlist
ليكونstatic
vegerot لا يمكنك استخدام
const
مباشرة في نطاقclass
، لذا فإن البنية غير صحيحة.
@ 7kms بلدي سيئة. لقد قمت بنسخ ولصق الكثير. ما قصدت قوله هو
class Class {
private list = <const>[
'room',
'room_with_gifter',
'user_send'
];
private withType: typeof list[number];
// OR
private withType2: typeof this.list[number];
}
الخ كل لا يعمل.
أيضًا ، بالنسبة لحالة الاستخدام الخاصة بي ، لا يمكنني تعيين القائمة لتكون ثابتة
@ 7kms
في [email protected] وما فوق. حلها هكذا
export const type = <const>[ 'room', 'room_with_gifter', 'user_send' ]; export interface Activity { id?: string; type: typeof type[number]; }
الآن ماذا لو كان لدي هذا في الفصل؟
class Class { const list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; const withType: typeof list[number]; }
لا يعمل. أنا أيضًا لا أستطيع أن أفعل
this.list[number]
. أيضا ، من أجل خاصتي
usecase ، لا يمكنني تعيينlist
ليكونstatic
vegerot لا يمكنك استخدام
const
مباشرة في نطاقclass
، لذا فإن البنية غير صحيحة.@ 7kms بلدي سيئة. لقد قمت بنسخ ولصق الكثير. ما قصدت قوله هو
class Class { private list = <const>[ 'room', 'room_with_gifter', 'user_send' ]; private withType: typeof list[number]; // OR private withType2: typeof this.list[number]; }
الخ كل لا يعمل.
أيضًا ، بالنسبة لحالة الاستخدام الخاصة بي ، لا يمكنني تعيين القائمة لتكون ثابتة
class Class {
private list = [
"room",
"room_with_gifter",
"user_send"
] as const
private withType: Class["list"][number]
}
vegerot ماذا عن هذا؟
eyalch هذا رائع! شكرا لك. اعتقدت أن الحل سيتضمن typeof
أو شيء من هذا القبيل. هل يمكنك تقديم شرح سريع لكيفية عمل ذلك ، أو ربطني بالكتيب حيث تتم مناقشة ذلك؟
eyalch هذا رائع! شكرا لك. اعتقدت أن الحل سيتضمن
typeof
أو شيء من هذا القبيل. هل يمكنك تقديم شرح سريع لكيفية عمل ذلك ، أو ربطني بالكتيب حيث تتم مناقشة ذلك؟
vegerot بالتأكيد ، أعتقد أنه "نوع فهرس". تجده هنا في الكتيب: https://www.typescriptlang.org/docs/handbook/advanced-types.html#index -types
يسرني أني استطعت المساعدة!
مرحبًا٪ username٪ ، إذا كان الحل ElementType
لا يناسبك أيضًا ،
انتبه إلى as const
بعد المصفوفة . إنه أمر بالغ الأهمية
التعليق الأكثر فائدة
في [email protected] وما فوق. حلها هكذا