简体   繁体   English

Typescript如何实现工厂模式

[英]Typescript how to implement factory pattern

I'm newbie to typescript, and trying to implement kind of factory pattern. 我是打字手的新手,并尝试实现某种工厂模式。 Here is the example. 这是例子。 I have two methods "getCat" and "getDog", and each of them takes different arguments. 我有两个方法“ getCat”和“ getDog”,每个方法采用不同的参数。 And an object "pet" which maps key and corresponding method. 以及映射密钥和相应方法的对象“宠物”。 I am trying to create a factory "getPet", pass in "type" and corresponding arguments. 我试图创建一个工厂“ getPet”,传入“类型”和相应的参数。

But I am not sure how can the "arg" been typed (now it is any), and how to restrict if type is 'cat', the argument is for 'cat' (that has meow method)? 但是我不确定如何键入“ arg”(现在是任何类型),以及如何限制类型是否为“ cat”,参数是否为“ cat”(具有喵声方法)?

interface CatArg {name: string; meow: () => string; }
interface DogArg {name: string; bark: () => string; }


function getCat({name: string, meow}: CatArg) {
    meow();
}

function getDog({name: string, bark}: DogArg) {
    bark();
}

const pet = {
    cat: getCat,
    dog: getDog
};

function playWithPet(type: 'cat' | 'dog', arg: any) {
    switch (type) {
        case 'cat':
            return pet.cat(arg);
        case 'dog':
            return pet.dog(arg);
    }
}

playWithPet('cat', {name: 'Kitty', meow: () => 'dont touch me'});
playWithPet('dog', {name: 'Bella', bark: () => 'play with me'});

You can use function overloading like so 您可以像这样使用函数重载

function playWithPet( type: 'cat', arg: CatArg): void
function playWithPet( type: 'dog', arg: DogArg ): void
function playWithPet( type, arg ) {
    switch (type) {
        case 'cat':
            return pet.cat(arg);
        case 'dog':
            return pet.dog(arg);
    }
}

Note: I'm returning void because your getCat and getDog aren't returning anything. 注意:我返回的是void,因为您的getCatgetDog没有返回任何内容。 So this function should make it clear nothing is returned, overall I would refactor the code. 因此,此函数应明确表示什么都没有返回,总的来说,我将重构代码。

Now it will check that the correct object is passed for the second parameter 现在它将检查是否为第二个参数传递了正确的对象

Another way to do it is this way 另一种方法是这种方式

interface PlayWithPet {
  ( type: 'cat', arg: CatArg ): void
  ( type: 'dog', arg: DogArg ): void
}

const playWithPet: PlayWithPet = ( type, arg ) => {
    switch (type) {
        case 'cat':
            return pet.cat(arg);
        case 'dog':
            return pet.dog(arg);
    }
}

In general TypeScript does not encourage such usage but with 3.2+ you can make it work by using tuple types for rest arguments together with discriminated unions: 通常,TypeScript不鼓励这种用法,但是在3.2+中,您可以通过将元组类型用于rest参数以及可区分的并集来使其工作:

function playWithPet(...args: ['cat', CatArg] | ['dog', DogArg]): void {
  switch (args[0]) {
  case 'cat':
    return pet.cat(args[1]);
  case 'dog':
    return pet.dog(args[1]);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM