TypeScript: truyền HTMLEuity


197

Có ai biết cách truyền trong TypeScript không?

Tôi đang cố gắng làm điều này:

var script:HTMLScriptElement = document.getElementsByName("script")[0];
alert(script.type);

nhưng nó cho tôi một lỗi:

Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement'
(elementName: string) => NodeList

Tôi không thể truy cập thành viên 'loại' của thành phần tập lệnh trừ khi tôi chuyển nó thành đúng loại, nhưng tôi không biết làm thế nào để làm điều này. Tôi đã tìm kiếm các tài liệu và mẫu, nhưng tôi không thể tìm thấy bất cứ điều gì.


Lưu ý rằng vấn đề truyền này không còn tồn tại trong 0.9 - Xem câu trả lời của @Steve bên dưới.
Greg Gum

@GregGum Tôi không thấy câu trả lời của Steve
Steve Schrab

Câu trả lời:


255

TypeScript sử dụng '<>' để bao quanh các phôi, do đó, phần trên trở thành:

var script = <HTMLScriptElement>document.getElementsByName("script")[0];

Tuy nhiên, thật không may, bạn không thể làm:

var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0];

Bạn nhận được lỗi

Cannot convert 'NodeList' to 'HTMLScriptElement[]'

Nhưng bạn có thể làm:

(<HTMLScriptElement[]><any>document.getElementsByName(id))[0];

Tôi nghĩ rằng họ nên xem xét thêm về vấn đề này, giả sử bạn sử dụng $ ('[type: input]'). mỗi (hàm (chỉ mục, phần tử) và bạn cần phần tử được chuyển thành HTMLInputEuity hoặc HTMLSelectEuity tùy thuộc vào thuộc tính nào bạn cần đặt / get, truyền sử dụng (phần tử <HTMLSelectE bổ sung> <any>) .selectedIndex = 0; thêm () xung quanh phần tử, loại xấu xí
rekna


Về lâu dài (sau khi hết 0,9), bạn sẽ có thể truyền nó thành một cái gì đó như NodeList <HtmlScriptEuity>, cộng với getElementsByName sẽ có thể sử dụng các kiểu ghi đè chuỗi ký tự để có quyền này mà không cần bất kỳ phép truyền nào!
Peter Burns

3
sau 1.0, cú pháp sẽ là(<NodeListOf<HTMLScriptElement>>document.getElementsByName(id))[0];
Will Huang

1
Bạn cũng có thể sử dụng như để đúc. var script = document.getElementsByName ("script") [0] dưới dạng HTMLScriptEuity;
JGFMK

36

Kể từ TypeScript 0.9, lib.d.tstệp sử dụng chữ ký quá tải chuyên dụng trả về các loại chính xác cho các cuộc gọi đến getElementsByTagName.

Điều này có nghĩa là bạn không còn cần phải sử dụng các xác nhận loại để thay đổi loại:

// No type assertions needed
var script: HTMLScriptElement = document.getElementsByTagName('script')[0];
alert(script.type);

Làm thế nào để bạn làm điều đó trong ký hiệu đối tượng? tức là tôi không thể làm {name: <HTMLInputEuity>: document.querySelector ('# app-form [name]'). value,}
Nikos

3
cái này hoạt động: name: (<HTMLInputEuity> document.querySelector ('# app-form [name]')). value,
Nikos

21

Bạn luôn có thể hack hệ thống loại bằng cách sử dụng:

var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];

sử dụng <bất kỳ> cho phép thoát kiểm tra kiểu, không lý tưởng nhưng mát mẻ trong khi phát triển
tit

21

Đừng gõ diễn viên. Không bao giờ. Sử dụng loại bảo vệ:

const e = document.getElementsByName("script")[0];
if (!(e instanceof HTMLScriptElement)) 
  throw new Error(`Expected e to be an HTMLScriptElement, was ${e && e.constructor && e.constructor.name || e}`);
// locally TypeScript now types e as an HTMLScriptElement, same as if you casted it.

Hãy để trình biên dịch thực hiện công việc cho bạn và nhận lỗi khi các giả định của bạn sai.

Nó có thể trông quá mức trong trường hợp này, nhưng nó sẽ giúp bạn rất nhiều nếu bạn quay lại sau và thay đổi bộ chọn, chẳng hạn như thêm một lớp bị thiếu trong dom, chẳng hạn.


13

Để kết thúc với:

  • một Arrayđối tượng thực tế (không NodeListmặc quần áo như một Array)
  • một danh sách được đảm bảo chỉ bao gồm HTMLElements, không Nodeđược ép buộc thành HTMLElements
  • một cảm giác mờ nhạt ấm áp để làm điều đúng

Thử cái này:

let nodeList : NodeList = document.getElementsByTagName('script');
let elementList : Array<HTMLElement> = [];

if (nodeList) {
    for (let i = 0; i < nodeList.length; i++) {
        let node : Node = nodeList[i];

        // Make sure it's really an Element
        if (node.nodeType == Node.ELEMENT_NODE) {
            elementList.push(node as HTMLElement);
        }
    }
}

Thưởng thức.


10

Chúng ta có thể gõ biến của mình với kiểu trả về rõ ràng :

const script: HTMLScriptElement = document.getElementsByName(id).item(0);

Hoặc khẳng định (cần thiết với TSX ):

const script = document.getElementsByName(id).item(0) as HTMLScriptElement;

Hoặc trong trường hợp đơn giản hơn, khẳng định với cú pháp khung góc .


Một xác nhận kiểu giống như một kiểu đúc trong các ngôn ngữ khác, nhưng không thực hiện kiểm tra hoặc tái cấu trúc dữ liệu đặc biệt. Nó không có tác động thời gian chạy, và được sử dụng hoàn toàn bởi trình biên dịch.

Tài liệu:

TypeScript - Kiểu cơ bản - Xác nhận kiểu


9

Chỉ cần làm rõ, điều này là chính xác.

Không thể chuyển đổi 'NodeList' thành 'HTMLScriptEuity []'

vì a NodeListkhông phải là một mảng thực tế (ví dụ: nó không chứa.forEach , .slice, .push, vv ...).

Do đó, nếu nó đã chuyển đổi thành HTMLScriptElement[]trong hệ thống loại, bạn sẽ không gặp lỗi loại nếu bạn đã cố gắng gọi Array.prototypecác thành viên trên nó vào thời gian biên dịch, nhưng nó sẽ thất bại trong thời gian chạy.


1
cho rằng đó là chính xác, tuy nhiên không hoàn toàn hữu ích. cách khác là đi qua 'bất kỳ', không cung cấp loại kiểm tra hữu ích nào ...
Spongman

3

Điều này dường như để giải quyết vấn đề, sử dụng các [index: TYPE]loại truy cập mảng, chúc mừng.

interface ScriptNodeList extends NodeList {
    [index: number]: HTMLScriptElement;
}

var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0];

1

Có thể được giải quyết trong tệp khai báo (lib.d.ts) nếu TypeScript sẽ định nghĩa HTMLCollection thay vì NodeList làm kiểu trả về.

DOM4 cũng chỉ định đây là loại trả về chính xác, nhưng thông số kỹ thuật DOM cũ hơn ít rõ ràng hơn.

Xem thêm http://typescript.codeplex.com/workitem/252


0

Vì đó là một NodeList, không phải là một Array, bạn thực sự không nên sử dụng dấu ngoặc hoặc chuyển sang Array. Cách thuộc tính để có được nút đầu tiên là:

document.getElementsByName(id).item(0)

Bạn chỉ có thể sử dụng:

var script = <HTMLScriptElement> document.getElementsByName(id).item(0)

Hoặc, mở rộng NodeList:

interface HTMLScriptElementNodeList extends NodeList
{
    item(index: number): HTMLScriptElement;
}
var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'),
    script = scripts.item(0);

1
CẬP NHẬT Đúc bây giờ trông như thế này: const script = document.getElementsByName(id).item(0) as HTMLScriptElement;
Mike Keesey

Đó là, "trông như thế này" cho TS 2.3.
markeissler

0

Tôi cũng muốn giới thiệu các hướng dẫn sitepen

https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript/ (xem bên dưới) và https://www.sitepen.com/blog/2014/08/22/advified -typescript-khái niệm-lớp-loại /

TypeScript cũng cho phép bạn chỉ định các kiểu trả về khác nhau khi một chuỗi chính xác được cung cấp làm đối số cho hàm. Ví dụ: khai báo môi trường xung quanh của TypeScript cho phương thức createEuity của DOM trông như thế này:

createElement(tagName: 'a'): HTMLAnchorElement;
createElement(tagName: 'abbr'): HTMLElement;
createElement(tagName: 'address'): HTMLElement;
createElement(tagName: 'area'): HTMLAreaElement;
// ... etc.
createElement(tagName: string): HTMLElement;

Điều này có nghĩa, trong TypeScript, khi bạn gọi ví dụ: document.createEuity ('video'), TypeScript biết giá trị trả về là HTMLVideoE bổ sung và sẽ có thể đảm bảo bạn đang tương tác chính xác với API Video DOM mà không cần phải xác nhận.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.