Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a type member to return values for better TypeScript usage #81

Open
krisztianb opened this issue Sep 14, 2021 · 0 comments
Open

Add a type member to return values for better TypeScript usage #81

krisztianb opened this issue Sep 14, 2021 · 0 comments

Comments

@krisztianb
Copy link
Contributor

krisztianb commented Sep 14, 2021

I'm currently working on the TypeScript type definitions of this library as stated here: #77

I noticed that some functions return either an object with the result or an object with an error string. For example swe_houses which you can find here:

/**
 * int swe_houses(double tjd_ut, double geolat, double geolon, int hsys, double *cusps, double *ascmc)
 * =>
 * int swe_houses(double tjd_ut, double geolat, double geolon, string hsys) {
 *   house: [double],
 *   ascendant: double,
 *   mc: double,
 *   armc: double,
 *   vertex: double,
 *   equatorialAscendant: double,
 *   kochCoAscendant: double,
 *   munkaseyCoAscendant: double,
 *   munkaseyPolarAscendant: double,
 *   error: string
 * }
 */
NAN_METHOD(node_swe_houses) {

    // **some code removed for simplicity**

	if (rflag < 0) {
		Nan::Set(result,Nan::New<String> ("error").ToLocalChecked(), Nan::New<String> ("Can't calculate houses.").ToLocalChecked());
	} else {
		for (size_t i = 0; i < cuspsCount; i ++) {
			Nan::Set(house,Nan::New<Number> (i), Nan::New<Number> (cusps [i + 1]));
		};

		Nan::Set(result,Nan::New<String> ("house").ToLocalChecked(), house);
		Nan::Set(result,Nan::New<String> ("ascendant").ToLocalChecked(), Nan::New<Number> (ascmc [SE_ASC]));
		Nan::Set(result,Nan::New<String> ("mc").ToLocalChecked(), Nan::New<Number> (ascmc [SE_MC]));
		Nan::Set(result,Nan::New<String> ("armc").ToLocalChecked(), Nan::New<Number> (ascmc [SE_ARMC]));
		Nan::Set(result,Nan::New<String> ("vertex").ToLocalChecked(), Nan::New<Number> (ascmc [SE_VERTEX]));
		Nan::Set(result,Nan::New<String> ("equatorialAscendant").ToLocalChecked(), Nan::New<Number> (ascmc [SE_EQUASC]));
		Nan::Set(result,Nan::New<String> ("kochCoAscendant").ToLocalChecked(), Nan::New<Number> (ascmc [SE_COASC1]));
		Nan::Set(result,Nan::New<String> ("munkaseyCoAscendant").ToLocalChecked(), Nan::New<Number> (ascmc [SE_COASC2]));
		Nan::Set(result,Nan::New<String> ("munkaseyPolarAscendant").ToLocalChecked(), Nan::New<Number> (ascmc [SE_POLASC]));
	};

    // **some code removed for simplicity**

};

As you can see the comments lie a bit in telling you that everything is in one object. But if you look at the code you see that you either get an object with the result details or an object with just an error string.

Now the typing of this return value would look like this:

{
    house: number[];
    ascendant: number;
    mc: number;
    armc: number;
    vertex: number;
    equatorialAscendant: number;
    kochCoAscendant: number;
    munkaseyCoAscendant: number;
    munkaseyPolarAscendant: number;
}
| {
    error: string;
}

After calling this method however one has to know which kind of object the result is. To make this check simpler I would like to propose the usage of discriminating unions in the result type.

This would mean that we could add a type: "ok" | "error" member to each object and make the usage of the library functions simpler. So the typing could look like this:

{
    type: "ok";
    house: number[];
    ascendant: number;
    mc: number;
    armc: number;
    vertex: number;
    equatorialAscendant: number;
    kochCoAscendant: number;
    munkaseyCoAscendant: number;
    munkaseyPolarAscendant: number;
}
| {
    type: "error";
    error: string;
}

The calling code could then look like this (with correct type resolution in TypeScript):

const result = swisseph.swe_houses(123456.789, 1, 1, "P");
if (result.type === "ok") {
    console.log(result.ascendant);
} else {
    console.log(result.error);
}

I think this should be fairly simple and straight-forward to achieve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant