TypeScript com KnockoutJS

137

Existe algum exemplo de uso do TypeScript com o KnockoutJS? Só estou curioso para saber como eles trabalhariam juntos.

Editar

Aqui está o que eu tenho, parece funcionar

declare var ko: any;
declare var $: any;
class ViewModel {
    x = ko.observable(10);
    y = ko.observable(10);

}

$(() => {
    ko.applyBindings(new ViewModel());
});

Isso gera o seguinte Javascript:

var ViewModel = (function () {
    function ViewModel() {
        this.x = ko.observable(10);
        this.y = ko.observable(10);
    }
    return ViewModel;
})();
$(function () {
    ko.applyBindings(new ViewModel());
});
CallumVass
fonte
6
Fiquei um pouco confuso com a palavra-chave "declare" usada em conjunto com "var" até encontrar a seção sobre declarações ambientais na especificação. Faz todo o sentido agora: typescriptlang.org/Content/… .
Rex Miller
2
Em Typescript 0,9 temos genéricos, o que lhe dá digitado observáveis: ko.observable<number>(10). Eu escrevi um blogpost com algumas informações mais detalhadas: ideasof.andersaberg.com/idea/12/...
Anders

Respostas:

108

Veja DefinitelyTyped .

"Repositório de definições de tipo TypeScript para bibliotecas JavaScript populares"

George Mavritsakis
fonte
3
Esta pode ser uma pergunta idiota, mas você pode explicar o que exatamente é uma definição de tipo TypeScript? É puramente para que você possa usar as funções de biblioteca em um arquivo compilado TypeScript sem que o compilador se queixe? Se for esse o caso, você não precisaria fazer referência à definição em seu aplicativo, justamente quando compilar os arquivos ts, correto?
undeniablyrob
9
Esse é exatamente o caso. Se você estivesse escrevendo seu código de texto datilografado no bloco de notas, precisaria apenas das definições em tempo de compilação. Por outro lado, um dos pontos positivos do texto datilografado é que é mais fácil para a inteligência do visual studio (e outros editores através de plugins) entender seu código e ajuda muito na conclusão automática e na verificação de tipo e erro (muito mais que JavaScript). É por isso que usamos arquivos de definição para código escrito em JavaScript, a fim de fornecer verificação de tipo de texto datilografado. É claro que você pode declarar libs como "qualquer", mas isso não é bom. Espero que ajudei!
George Mavritsakis 01/12/12
5
Observe que a chave é adicionar /// <reference path="knockout-2.2.d.ts" />à parte superior do seu arquivo .ts para que ele pegue as definições.
Aidan Ryan
Não vejo nocaute em nenhum lugar da lista .... removido ?? mudou-se?? frustrado
Jester
58

Eu fiz essa pequena interface para obter tipos estáticos para o Knockout:

interface ObservableNumber {
        (newValue: number): void;               
        (): number;                             
        subscribe: (callback: (newValue: number) => void) => void;
}
interface ObservableString {
        (newValue: string): void;               
        (): string;                             
        subscribe: (callback: (newValue: string) => void) => void;
}
interface ObservableBool {
    (newValue: bool): void;             
    (): bool;                               
    subscribe: (callback: (newValue: bool) => void) => void;
}

interface ObservableAny {
    (newValue: any): void;              
    (): any;                                
    subscribe: (callback: (newValue: any) => void) => void;
}

interface ObservableStringArray {
    (newValue: string[]): void;
    (): string[];
    remove: (value: String) => void;
    removeAll: () => void;
    push: (value: string) => void;
    indexOf: (value: string) => number;
}

interface ObservableAnyArray {
    (newValue: any[]): void;
    (): any[];
    remove: (value: any) => void;
    removeAll: () => void;
    push: (value: any) => void;
}

interface Computed {
    (): any;
}

interface Knockout {
    observable: {
        (value: number): ObservableNumber;
        (value: string): ObservableString;
        (value: bool): ObservableBool;
        (value: any): ObservableAny;
    };
    observableArray: {
        (value: string[]): ObservableStringArray;
        (value: any[]): ObservableAnyArray;
    };
    computed: {
        (func: () => any): Computed;
    };
}

Coloque-o em "Knockout.d.ts" e faça referência a partir de seus próprios arquivos. Como você pode ver, ele se beneficiaria muito com os genéricos (que são fornecidos de acordo com as especificações).

Eu fiz apenas algumas interfaces para ko.observable (), mas ko.computed () e ko.observableArray () podem ser facilmente adicionados no mesmo padrão. Atualização: Corrigi as assinaturas de subscribe () e adicionei exemplos de computed () e observableArray ().

Para usar em seu próprio arquivo, adicione-o na parte superior:

/// <reference path="./Knockout.d.ts" />
declare var ko: Knockout;
Sten L
fonte
2
@JcFx: O que Anders se referiu foi provavelmente a opção de pegar um arquivo .ts TypeScript e gerar um arquivo de declaração de interface .d.ts. Não há como usar JavaScript sem tipo regular e descobrir magicamente os tipos. O problema com o JS (que TypeScripts tenta resolver) é que não há como o programador declarar sua intenção de que uma variável esteja em conformidade com um tipo específico. Quando você diz x = 'hello'em JS, não sabemos se você pretendeu dizer em algum lugar posteriormente x = 34. Portanto, não podemos deduzir nada sobre o tipo de x.
Sten L
@JcFx: na verdade, você pode estar certo de que algumas informações de tipo limitado podem ser derivadas de JS simples. Deixe-me saber como vai quando você tenta!
Sten L
datilografado está adicionando genéricos.
Daniel A. White
6

Nada mudaria em termos da maneira como as ligações de knockout são declaradas na marcação, no entanto, obteríamos a bondade intellisense assim que as interfaces fossem escritas para a biblioteca de knockout. Nesse aspecto, funcionaria exatamente como o jquery Sample , que possui um arquivo datilografado contendo interfaces para a maioria das APIs do jQuery .

Eu acho que se você se livrar das duas declarações de variáveis ​​para ko e $, seu código funcionará. Eles estão ocultando as variáveis ​​ko e $ reais que foram criadas quando os scripts knockout e jquery foram carregados.

Eu tive que fazer isso para portar o projeto de modelo do visual studio para nocaute:

app.ts:

class GreeterViewModel {
    timerToken: number;
    utcTime: any;

    constructor (ko: any) { 
        this.utcTime = ko.observable(new Date().toUTCString());
        this.start();
    }

    start() {
        this.timerToken = setInterval(() => this.utcTime(new Date().toUTCString()), 500);
    }
}

window.onload = () => {
    // get a ref to the ko global
    var w: any;
    w = window;
    var myKO: any;
    myKO = w.ko;

    var el = document.getElementById('content');
    myKO.applyBindings(new GreeterViewModel(myKO), el);
};

default.htm:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="Scripts/knockout-2.1.0.debug.js" type="text/javascript"></script>
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>

    <div id="content" data-bind="text: utcTime" />
</body>
</html>
Jeremy Danyow
fonte
1
Não é postar em ko a todo tipo construtor de exagero
Simon_Weaver
3

Ok, basta usar o seguinte comando para importar os tipos de knockout ou tds.

npm install @types/knockout

Isso criará um diretório @types no diretório node_modules do seu projeto e o arquivo de definição do tipo knockout do índice estará em um diretório chamado knockout. Em seguida, através de uma referência de barra tripla para o arquivo de tipos. Isso fornecerá ótimos recursos de IDE e TypeScript.

/// <reference path="../node_modules/@types/knockout/index.d.ts" />

Por fim, basta usar uma declaração declare para trazer a variável ko para o escopo. Isso é fortemente tipado, então olá intellisense.

declare var ko: KnockoutStatic;

Então agora você pode usar o KO como nos seus arquivos javascript.

insira a descrição da imagem aqui

Espero que isto ajude.

SimperT
fonte