给定类类型,推断Typescript中其他参数的类型

给定类类型,推断Typescript中其他参数的类型,typescript,Typescript,我试图创建一个有两个参数的函数,其中第二个参数的类型基于第一个参数的类型。我可以看到几个线程,这个问题可能是重复的,但键入语法可能变得如此复杂,我已经摆弄了一段时间,现在不能得到它的权利 class Mammal { } class Bird { } function stuff(classType: typeof Mammal | typeof Bird, arg: number or string depends on first param) { if (classType ex

我试图创建一个有两个参数的函数,其中第二个参数的类型基于第一个参数的类型。我可以看到几个线程,这个问题可能是重复的,但键入语法可能变得如此复杂,我已经摆弄了一段时间,现在不能得到它的权利

class Mammal { }
class Bird { }

function stuff(classType: typeof Mammal | typeof Bird, arg: number or string depends on first param) {
    if (classType extends Mammal) {
        console.log(arg * 5);
    } else {
        console.log(arg.split(" "))
    }
}

stuff(Mammal, 5);  // want this to be valid

stuff(Bird, "Hello world"); // want this to be valid

stuff(Bird, 5); // want this to be invalid

这就是为什么为了区分
哺乳动物
鸟类
我们需要创建一些静态属性来区分两者的原因

另一件事是,当我们在例如
哺乳动物
中询问此属性时,将没有,因为
哺乳动物
具有所有非静态属性,我们需要使用
哺乳动物的类型
,以便与静态属性有接口。这就是为什么在实现中我使用的是
typeof M
,而不是
M

一些重要信息:

  • M扩展了哺乳动物的类型|鸟类的类型
    意味着我们允许或分类哺乳动物或鸟类,如果我只想说
    哺乳动物|鸟类
    的话,这意味着我想要得到的是类的实例,而不是类本身
  • A extends(M extends(typeof meanimal)?number:string)
    -条件类型,如果我们将
    meanimal
    类型设为
    M
    我们有第二个参数
    number
    如果不是
    string
  • classType.type===“哺乳动物”
    由于具有静态属性,我们可以在条件下使用它
  • (arg作为数字)
    需要进行类型断言,因为第一个属性的判别式对第二个属性不起作用

通过使用一种对象/数组类型的参数,可以避免类型断言。但我不推荐这种方法,不过你可以这样做:

type MammalArgs = [typeof Mammal, number]
type BirdsArgs = [typeof Bird, string];

const isMammalClass = (x: MammalArgs | BirdsArgs): x is MammalArgs => x[0].type === 'mammal'
const isBirdArgs = (x: MammalArgs | BirdsArgs): x is BirdsArgs => x[0].type === 'bird'
function stuff<
M extends typeof Mammal | typeof Bird,
A extends (M extends (typeof Mammal) ? MammalArgs : BirdsArgs)>
(...args: A) {
    if (isMammalClass(args)) {
        console.log(args[1] * 5); // no type assertion
    }
    if (isBirdArgs(args)) {
        console.log(args[1].split(" ")); // no type assertion
    }
}
type哺乳动物args=[哺乳动物类型,编号]
type BirdsArgs=[typeof Bird,string];
const isMammalClass=(x:MadamalArgs | BirdArgs):x是MadamalArgs=>x[0]。类型==='Madamal'
常量isBirdArgs=(x:Madamalargs | BirdsArgs):x是BirdsArgs=>x[0]。类型==='bird'
功能材料<
哺乳动物的M型|鸟类的M型,
A扩展(M扩展(哺乳动物的类型)?哺乳动物args:BirdsArgs)>
(…args:A){
if(isMammalClass(args)){
console.log(args[1]*5);//无类型断言
}
if(isBirdArgs(args)){
console.log(args[1].split(“”);//无类型断言
}
}
我在上面所做的是将我们的参数加入一个类型
[typeof哺乳类,number]|[typeof Bird,string]
,以实现第一个参数中的判别式与第二个参数之间的关系。在一种类型中同时具有这两种类型允许这种关系。问题是我需要创建两个类型保护,还需要直接使用数组,因为任何解构都会破坏我们的类型缩小。我将选择使用类型断言的第一种方法

class Mammal {}
class Bird {}
type MammalIsBird 
  = Mammal extends Bird 
  ? Bird extends Mammal 
  ? true 
  : false 
  : false // evaluates to true, Mammal and Bird are equal
type MammalArgs = [typeof Mammal, number]
type BirdsArgs = [typeof Bird, string];

const isMammalClass = (x: MammalArgs | BirdsArgs): x is MammalArgs => x[0].type === 'mammal'
const isBirdArgs = (x: MammalArgs | BirdsArgs): x is BirdsArgs => x[0].type === 'bird'
function stuff<
M extends typeof Mammal | typeof Bird,
A extends (M extends (typeof Mammal) ? MammalArgs : BirdsArgs)>
(...args: A) {
    if (isMammalClass(args)) {
        console.log(args[1] * 5); // no type assertion
    }
    if (isBirdArgs(args)) {
        console.log(args[1].split(" ")); // no type assertion
    }
}