จะใช้ Object.values ​​กับ typescript ได้อย่างไร?


137

ฉันกำลังพยายามสร้างสตริงที่คั่นด้วยจุลภาคจากวัตถุ

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const values = Object.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

จะทำกับ TypeScript ได้อย่างไร?

รับไฟล์ข้อผิดพลาด:

severity: 'Error'
message: 'Property 'values' does not exist on type 'ObjectConstructor'.'
at: '216,27'
source: 'ts'

คำตอบ:


107

โดยใช้ Object.keys แทน

const data = {
  a: "first",
  b: "second",
};

const values = Object.keys(data).map(key => data[key]);

const commaJoinedValues = values.join(",");
console.log(commaJoinedValues);

92
โปรดทราบว่านี่เป็นอีกทางเลือกหนึ่ง (ทางเลือกที่ดี!) ไม่ใช่คำตอบที่แท้จริงเกี่ยวกับวิธีใช้ ES7 Object.valuesใน TS เพื่อแก้ไขข้อผิดพลาดในการคอมไพล์ของ OP ในการทำเช่นนั้นคุณเพียงแค่ต้องการES2017ใน--libการตั้งค่าของคุณ
Aaron Beall

4
@Aaron โซลูชันของคุณซับซ้อนมากจนใครก็ตามที่เพิ่งใช้ typescript ไม่สามารถยอมรับได้ในการคอมไพล์คุณต้องเพิ่มES2017lib และต้องมีไลบรารี polyfills ที่ใช้งานได้ให้คำตอบที่แตกต่างกับคนอื่นคือราชา
holi-java

9
@ Holi-jave มันไม่ได้ "การแก้ปัญหาของฉัน" มันเป็นเพียงแค่วิธี TS และไม่ใช่เลยมาตรฐาน JS คุณสมบัติการทำงานเช่นการใช้ความพยายาม OP ES7/Object.values()ของ บางทีคุณอาจคิดว่ามันซับซ้อน (ฉันไม่เห็นด้วย) แต่นั่นเป็นเพียงลักษณะของการพยายามใช้คุณสมบัติในอนาคตเช่นObject.values()ปัจจุบัน มันเป็นแบบนี้เสมอมา แม้Object.keys()จะยังคงเป็นแบบ polyfilled หากคุณกำหนดเป้าหมาย ES3 หรือต้องการสนับสนุน IE8 (หวังว่าคุณจะไม่ทำอีกต่อไป!) โดยทั่วไปแล้วเป็นความคิดที่ดีในการทำความเข้าใจคุณสมบัติ ES การรองรับเบราว์เซอร์และการเติมแบบ polyfilling หากคุณกำลังพัฒนาเว็บ!
Aaron Beall

@Aaron ฉันไม่ได้บอกว่ามันซับซ้อน แต่สำหรับคนที่เพิ่งเริ่มใช้ typescript / javascript นั้นซับซ้อนกว่าและไม่ได้รับการยอมรับ
holi-java

1
ขอให้เรายังคงอภิปรายนี้ในการแชท
holi-java

231

Object.values()เป็นส่วนหนึ่งของ ES2017และข้อผิดพลาดในการคอมไพล์ที่คุณได้รับเป็นเพราะคุณต้องกำหนดค่า TS เพื่อใช้ไลบรารี ES2017 คุณอาจใช้ไลบรารี ES6 หรือ ES5 ในการกำหนดค่า TS ปัจจุบันของคุณ

โซลูชั่นการใช้งาน: ใช้es2017หรือes2017.objectของคุณในตัวเลือกคอมไพเลอร์--lib

ตัวอย่างเช่นการใช้tsconfig.json:

"compilerOptions": {
    "lib": ["es2017", "dom"]
}

โปรดทราบว่าการกำหนดเป้าหมาย ES2017 ด้วย TypeScript จะไม่ปล่อย polyfills ในเบราว์เซอร์สำหรับ ES2017 (หมายความว่าข้างต้นช่วยแก้ข้อผิดพลาดในการคอมไพล์ของคุณแต่คุณยังพบข้อผิดพลาดรันไทม์ได้เนื่องจากเบราว์เซอร์ไม่ได้ใช้ ES2017 Object.values) คุณจะต้องเติมเต็มโครงการของคุณ รหัสตัวเองถ้าคุณต้องการ และเนื่องจากObject.valuesเบราว์เซอร์ทั้งหมดยังไม่ได้รับการสนับสนุนอย่างดี (ในขณะที่เขียนนี้) คุณต้องการ polyfill อย่างแน่นอน: core-jsจะทำงานได้


1
@ErikvanVelzen คุณแก้ไขคำตอบเพื่อเปลี่ยนกรณีของES2017เป็นes2017แต่ AFAIK นี่ไม่จำเป็น แต่ฉันต้องการเรียนรู้อยู่เสมอมีเหตุผลในการเปลี่ยนแปลงหรือไม่?
Aaron Beall

2
^ เพื่อที่จะตอบคำถามของฉันเอง: ES2017, DOM(ตัวพิมพ์ใหญ่) เป็น บริษัท จดทะเบียนในtsc --initการแสดงความคิดเห็นเป็นค่าที่ถูกต้องและทำงานได้อย่างถูกต้องในคอมไพเลอร์ แต่สคี JSONเพียงระบุes2017, dom(ตัวพิมพ์เล็ก) ตัวเลือกเพื่อ JSON IDE / linter ประสงค์ธงES2017, DOMเป็น ค่าที่ไม่ถูกต้อง (แม้ว่าจะถูกต้องก็ตาม) สับสนเล็กน้อย
Aaron Beall

นั่นคือเหตุผล มันทำงานเป็นตัวพิมพ์ใหญ่ตามที่คุณทราบ tsc --helpแสดงตัวพิมพ์เล็ก
Erik van Velzen

core-js ไม่รวมอยู่ในเชิงมุมหรือไม่ถ้าไม่ใช่วิธีการเพิ่ม pollyfill นี้?
Samiullah Khan

1
@ Totty.js ไฟล์ไลบรารีที่ TS มีไว้สำหรับการตรวจสอบประเภทเท่านั้นกล่าวอีกนัยหนึ่งคือมันไม่ได้ปล่อยไฟล์ไลบรารี JS สำหรับสิ่งต่างๆเช่นObject.values(). ในคำอื่น ๆ ที่คุณจะได้รับรอบรวบรวมข้อผิดพลาด Object.values()แต่ยังคงใช้เป็นข้อผิดพลาดถ้าคุณทำงานในเบราว์เซอร์ที่ไม่ได้มี
Aaron Beall

18

คุณสามารถใช้Object.valuesใน TypeScript ได้โดยทำเช่นนี้(<any>Object).values(data)หากด้วยเหตุผลบางประการที่คุณไม่สามารถอัปเดตเป็น ES7 ใน tsconfig ได้


4
@Aaron ในขณะที่โพสต์มีความคิดเห็นที่ระบุว่าผู้คนที่ใช้ Angular เวอร์ชันเฉพาะมีปัญหาในการอัปเดต lib ซึ่งมันใช้งานไม่ได้ นั่นคือเหตุผลที่ฉันใส่if for some reason you can't update to ES7 in tsconfig
mtpultz

12

ฉันได้เพิ่มเป้าหมายในtsconfig.jsonการเปิดใช้งานคุณสมบัตินี้ใน TypeScript

{
    "compilerOptions": {
        "target": "es2017",
        ......
    }
}

การเปลี่ยนเป้าหมายไม่ใช่วิธีแก้ปัญหาในกรณีที่คุณต้องการคงความเข้ากันได้กับเบราว์เซอร์รุ่นเก่า typescript ต้องสามารถถ่ายทอดไวยากรณ์ ES2017 เป็น ES2015 ได้
สุ่ม

11

แทน

Object.values(myObject);

ใช้

Object["values"](myObject);

ในกรณีตัวอย่างของคุณ:

const values = Object["values"](data).map(x => x.substr(0, x.length - 4));

สิ่งนี้จะซ่อนข้อผิดพลาดของคอมไพเลอร์ ts


1
คุณเป็นอัจฉริยะ (^ - ') b
harufumi.abe

องค์ประกอบโดยปริยายมีประเภท 'ใด ๆ ' เนื่องจากประเภท 'ObjectConstructor' ไม่มี index signature.ts (7017)
Tyguy7

6
นี่เป็นการใช้ TS ในทางที่ผิด คุณควรกำหนดค่าคอมไพลเลอร์ด้วยการlibตั้งค่าเพื่อให้สอดคล้องกับวิธีการใช้งานของคอมไพลเลอร์ไม่ใช่เจตนาหนีคอมไพเลอร์
Aaron Beall

1
@AaronBeall เป็นการใช้งานที่ดีหากมีเหตุผลบางอย่างที่คุณไม่สามารถอัพเกรดเป็น es2017 ได้
Dino

@Dino คุณไม่จำเป็นต้องอัปเกรดเป็น es2017 คุณสามารถใช้core-jsเพื่อทำ polyfill จนถึง ES5 ได้ TypeScript ไม่มีรันไทม์การlibตั้งค่าเป็นเพียงเพื่อให้ได้รับการตรวจสอบประเภทที่ถูกต้อง
Aaron Beall

4

ฉันเพิ่งประสบปัญหานี้กับ Angular 6 โดยใช้ CLI และพื้นที่ทำงานเพื่อสร้างไลบรารีโดยใช้ng g library foo.

ในกรณีของฉันปัญหาอยู่tsconfig.lib.jsonในโฟลเดอร์ไลบรารีซึ่งไม่ได้es2017รวมอยู่ในlibส่วนนี้

ใครก็ตามที่พบปัญหานี้กับ Angular 6 คุณเพียงแค่ต้องแน่ใจว่าคุณได้อัปเดตตัวคุณtsconfig.lib.jsonเช่นเดียวกับแอปพลิเคชันของคุณtsconfig.json


ฉันใส่ es2017 ทั้งใน tsconfig.lib และ tsconfig.json แต่ฉันยังคงได้รับข้อผิดพลาด 'รายการไม่มีอยู่ในข้อผิดพลาด Object' เมื่อพยายามใช้รายการ ฉันควรเปลี่ยนแปลง / อัปเดตอะไรอีกหรือไม่?
มอริซ

ฉันเปลี่ยนเป้าหมายใน tsconfig.lib เป็น es2017 ในตอนนี้ แต่ก็ยังคงมีข้อผิดพลาดเหมือนเดิม
Maurice

3

การtslintกำหนดค่ากฎของฉันที่นี่จะแทนที่บรรทัดObject["values"](myObject)ด้วยObject.values(myObject).

สองตัวเลือกหากคุณมีปัญหาเดียวกัน:

(Object as any).values(myObject)

หรือ

/*tslint:disable:no-string-literal*/
`Object["values"](myObject)`

1
ทำไมคุณถึงต้องการใช้Object["values"]?
Aaron Beall

-4

วิธีที่ง่ายที่สุดคือโยนObjectto anyดังนี้:

const data = {"Ticket-1.pdf":"8e6e8255-a6e9-4626-9606-4cd255055f71.pdf","Ticket-2.pdf":"106c3613-d976-4331-ab0c-d581576e7ca1.pdf"};
const obj = <any>Object;
const values = obj.values(data).map(x => x.substr(0, x.length - 4));
const commaJoinedValues = values.join(',');
console.log(commaJoinedValues);

และ voila - ไม่มีข้อผิดพลาดในการรวบรวม;)


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.