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

Use Flow or Typescript #73

Closed
Mocha-- opened this issue Nov 19, 2017 · 27 comments
Closed

Use Flow or Typescript #73

Mocha-- opened this issue Nov 19, 2017 · 27 comments

Comments

@Mocha--
Copy link

Mocha-- commented Nov 19, 2017

Hi,

Is it possible to incorporate typescript definition files into this fantastic project or maintain typescript definition files in @types? I am sure this would definitely benefit the whole community.

@icambron
Copy link
Member

icambron commented Nov 20, 2017

I'm kind of tempted to integrate Flow types directly into the code base and then, if possible, generate TypeScript definitions from that. The problem with external, independently maintained type defs is that they're perpetually out of date and either require constant fixing or whole separate suite of tests. So I'd rather have them be more "core".

So if someone wants to help Flow-ify the code and automatically generate TS defs from it, that would be great.

@tuananh
Copy link
Contributor

tuananh commented Nov 22, 2017

@icambron have you use flow before? any guidelines ? i can take a look sometimes this weekend but no guarantee as i have never used it before

@icambron
Copy link
Member

icambron commented Nov 22, 2017

I haven't really used Flow.

I do have two pointers pointer, though.

The first is that someone created external Flow types for a subset of Luxon, which you can find here: https://github.com/marudor/randomCats/blob/master/flow-typed/luxon.js

The second is that earlier in the development of Luxon I gave Flow types a shot. I just pushed that branch; it's called flow. It's hopelessly outdated compared to master and doesn't work because I gave up midway through. Also, I didn't know what I was doing. I think the main area in might be helpful in is the toolchain, which was working IIRC.

Anyway, those probably aren't too helpful, but they're what I have.

@icambron icambron changed the title Typescript Definition Files Use Flow or Typescript Nov 22, 2017
@andersfly
Copy link

I'm not trying to be biased here, but have you looked into TypeScript. Anyway I found that to be pretty easy to get going with - But thats just my opinion.

@icambron
Copy link
Member

Others are the Moment team (@marwahaha & @maggiepint) suggested I just let someone else maintain the types via TS on DefinitelyTyped. I'm good with that too, and it certainly reduces the footprint types leave on the codebase.

@andersfly
Copy link

andersfly commented Nov 22, 2017

I'm no expert, but I'm happy to give it a shot at TS definitions at some time.

Update: one simple way of doing it, is having a index.d.ts in the root of your project, like redux and others do it. https://github.com/reactjs/redux/blob/master/index.d.ts

I can make a POC index.d.ts for you if you interested

I never used Flow though, so I have no idea how it works with that.

@icambron
Copy link
Member

icambron commented Nov 22, 2017

I'm not all that clear on the language-level differences between TS and Flow either, but I do know that if the code is in this repo, I'd like it to be Flow, mostly because I understand the toolchain better.

Re: having an index.d.ts: we tried this in Moment and the result is that it's always broken. It's a bad middle ground. So the choices are:

  1. Completely integrated types in the actual code base with Flow. It can't break because then the code won't compile
  2. A totally external, community-maintained set of types (however people want to do it)

@chriskrycho
Copy link

The differences between TS and Flow types are just significant enough that auto-generating one from the other is… painful, and always incomplete. (I'm also not sure if there's anything out there to do Flow -> TS; my searching hasn't turned any up.)

FWIW, I'd be happy to help build a community-maintained (DefinitelyTyped) set of type defs for TS if you're going to go with Flow, and if you can generate Flowtype defs from the codebase that'll be super handy as a starting point for the TS defs.

@icambron
Copy link
Member

icambron commented Nov 24, 2017

That seems reasonable. If automatic Flow-> TS isn't possible that is at least the best option for TS. I'm still hopeful that Flow types can be done directly in the code base.

@Lakston
Copy link

Lakston commented Nov 27, 2017

Another vote for typescript types :)

I never created types for DefinitelyTyped but I'm willing to look at it and help when the project is on its way.

@tom10271
Copy link

tom10271 commented Dec 4, 2017

Where are contents inside API doc?

http://moment.github.io/luxon/docs/

I think it should not be too difficult to write a luxon.d.ts

@tom10271
Copy link

tom10271 commented Dec 4, 2017

Anyone want to give it a try? I guess at least we have a starting point. btw I have not use luxon at all but planning to use it in my Angular project.

It is 99.99% based on @marudor's work.

declare module 'luxon' {
    export = luxon;
}

declare namespace luxon {
    type DateTimeFormat = any;
    type ZoneOptions = {
        keepCalendarTime?: boolean,
    }

    type ToFormatOptions = {
        round: boolean,
    }

    type ISOTimeOptions = {
        suppressMilliseconds?: boolean,
        supressSeconds?: boolean,
    }

    type DateTimeOptions = {
        zone?: string | Zone,
        setZone?: boolean,
        locale?: string,
        outputCalendar?: string,
        numberingSystem?: string,
    }

    type DateTimeJSOptions = {
        zone?: string | Zone,
    }

    type DateObject = {
        yearh?: number,
        day?: number,
        ordinal?: number,
        weekYear?: number,
        weekNumber?: number,
        weekday?: number,
        hour?: number,
        minute?: number,
        second?: number,
        millisecond?: number,
        zone?: string | Zone,
        locale?: string,
        outputCalendar?: string,
        numberingSystem?: string,
    }

    type DiffOptions = {
        conversionAccuracy?: string,
    }

    class DateTime {
        static DATETIME_FULL: DateTimeFormat;
        static DATETIME_FULL_WITH_SECONDS: DateTimeFormat;
        static DATEIME_HUGE: DateTimeFormat;
        static DATEIME_HUGE_WITH_SECONDS: DateTimeFormat;
        static DATETIME_MED: DateTimeFormat;
        static DATETIME_MED_WITH_SECONDS: DateTimeFormat;
        static DATETIME_SHORT: DateTimeFormat;
        static DATETIME_SHORT_WITH_SECONDS: DateTimeFormat;
        static DATE_FULL: DateTimeFormat;
        static DATE_HUGE: DateTimeFormat;
        static DATE_MED: DateTimeFormat;
        static DATE_SHORT: DateTimeFormat;
        static TIME_24_SIMPLE: DateTimeFormat;
        static TIME_24_WITH_LONG_OFFSET: DateTimeFormat;
        static TIME_24_WITH_SECONDS: DateTimeFormat;
        static TIME_24_WITH_SHORT_OFFSET: DateTimeFormat;
        static TIME_SIMPLE: DateTimeFormat;
        static TIME_WITH_LONG_OFFSET: DateTimeFormat;
        static TIME_WITH_SECONDS: DateTimeFormat;
        static TIME_WITH_SHORT_OFFSET: DateTimeFormat;
        static fromHTTP(text: string, options?: DateTimeOptions): DateTime;
        static fromISO(text: string, options?: DateTimeOptions): DateTime;
        static fromJSDate(date: Date, options?: DateTimeJSOptions): DateTime;
        static fromMillis(ms: number, options?: DateTimeOptions): DateTime;
        static fromObject(obj: DateObject): DateTime;
        static fromRFC2822(text: string, options?: DateTimeOptions): DateTime;
        static fromString(text: string, format: string, options?: DateTimeOptions): DateTime;
        static fromStringExplain(text: string, format: string, options?: DateTimeOptions): Object;
        static invalid(reason: any): DateTime;
        static local(year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number, millisecond?: number): DateTime;
        static max(...dateTimes: DateTime[]): DateTime;
        static min(...dateTimes: DateTime[]): DateTime;
        static utc(year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number, millisecond?: number): DateTime;
        day: number;
        daysInMonth: number;
        daysInYear: number;
        hour: number;
        invalidReason: string;
        isInDST: boolean;
        isOffsetFixed: boolean;
        isValid: boolean;
        locale: string;
        millisecond: number;
        minute: number;
        month: number;
        monthLong: string;
        monthShort: string;
        numberingSystem: string;
        offset: number;
        offsetNameLong: string;
        offsetNameShort: string;
        ordinal: number | DateTime;
        outputCalendar: string;
        second: number;
        weekNumber: number;
        weekYear: number;
        weekdayLong: string;
        weekdayShort: string;
        year: number;
        zoneName: string;
        diff(other: DateTime, unit: string | string[], options?: DiffOptions): Duration;
        diffNow(unit: string | string[], options?: DiffOptions): Duration;
        endOf(unit: string): DateTime;
        equals(other: DateTime): boolean;
        get(unit: string): number;
        hasSame(other: DateTime, unit: string): boolean;
        minus(duration: Duration | number | Object): DateTime;
        plus(duration: Duration | number | Object): DateTime;
        reconfigure(properties: Object): DateTime;
        resolvedLocaleOptions(options?: Object): Object;
        set(values: DateObject): DateTime;
        setLocale(locale: any): DateTime;
        setZone(zone: string | Zone, options?: ZoneOptions): DateTime;
        startOf(unit: string): DateTime;
        toFormat(format: string, options?: ToFormatOptions): string;
        toHTTP(): string;
        toISO(options?: Object): string;
        toISODate(): string;
        toISOTime(options?: ISOTimeOptions): string;
        toISOWeekDate(): string;
        toJSDate(): Date;
        toJSON(): string;
        toLocal(): DateTime;
        toLocaleParts(options?: Object): any[];
        toObject(options?: { includeConfig?: boolean }): DateObject;
        toRFC2822(): string;
        toString(): string;
        toUTC(offset: number, options?: ZoneOptions): DateTime;
        until(other: DateTime): Duration;
        valueOf(): number;
    }

    type DurationOptions = {
        locale?: string,
        numberingSystem?: string,
        conversionAccuracy?: string,
    }

    type DurationObject = {
        years: number,
        months: number,
        weeks: number,
        days: number,
        hours: number,
        minutes: number,
        seconds: number,
        milliseconds: number,
    }

    class Duration {
        static fromISO(text: string, options?: DurationOptions): Duration;
        static fromMillis(count: number, options?: DurationOptions): Duration;
        static fromObject(object: DurationObject & DurationOptions): Duration;
        static invalid(reason?: string): Duration;
        days: number;
        hours: number;
        invalidReason: string;
        isValid: boolean;
        locale: string;
        milliseconds: number;
        minutes: number;
        months: number;
        numberingSystem: string;
        seconds: number;
        weeks: number;
        years: number;
        as(unit: string): number;
        equals(other: Duration): boolean;
        get(unit: string): number;
        minus(duration: Duration | number | Object): Duration;
        negate(): Duration;
        normalize(): Duration;
        plus(duration: Duration | number | Object): Duration;
        reconfigure(objectPattern: DurationOptions): Duration;
        set(values: DurationObject): Duration;
        shiftTo(...units: string[]): Duration;
        toFormat(format: string, options?: ToFormatOptions): string;
        toISO(): string;
        toJSON(): string;
        toObject(options?: { includeConfig?: boolean }): DurationObject & DurationOptions;
        toString(): string;
    }

    type EraLength = 'short' | 'long';
    type UnitLength = EraLength & 'numeric' | '2-digit' | 'narrow';
    type UnitOptions = InfoOptions & {
        numberingSystem?: string,
        outputCalendar?: string,
    }

    type InfoOptions = {
        locale?: string,
    }

    type Features = {
        intl: boolean,
        intlTokens: boolean,
        timezones: boolean,
    }

    class Info {
        static eras(length?: EraLength, options?: InfoOptions): string[];
        static features(): Features;
        static hasDST(zone: string | Zone): boolean;
        static meridiems(options?: InfoOptions): string[];
        static months(length?: UnitLength, options?: UnitOptions): string[];
        static monthsFormat(length?: UnitLength, options?: UnitOptions): string[];
        static weeksdays(length?: UnitLength, options?: UnitOptions): string[];
        static weekdaysFormat(length?: UnitLength, options?: UnitOptions): string[];
    }

    type IntervalObject = {
        start: DateTime,
        end: DateTime,
    }

    class Interval {
        static after(start: DateTime | DateObject | Date, duration: Duration | number | DurationObject): Interval;
        static before(end: DateTime | DateObject | Date, duration: Duration | number | DurationObject): Interval;
        static fromDateTimes(start: DateTime | DateObject | Date, end: DateTime | DateObject | Date): Interval;
        static fromISO(string: string, options?: DateTimeOptions): Interval;
        static invalid(reason?: string): Interval;
        static merge(intervals: Interval[]): [Interval];
        static xor(intervals: Interval[]): [Interval];
        end: DateTime;
        invalidReason: string;
        isValid: boolean;
        start: DateTime;
        abutsEnd(other: Interval): boolean;
        abutsStart(other: Interval): boolean;
        contains(dateTime: DateTime): boolean;
        count(unit?: string): number;
        difference(...intervals: Interval[]): Interval;
        divideEqually(numberOfParts?: number): Interval[];
        engulfs(other: Interval): boolean;
        equals(other: Interval): boolean;
        hasSame(unit: string): boolean;
        intersection(other: Interval): Interval;
        isAfter(dateTime: DateTime): boolean;
        isBefore(dateTime: DateTime): boolean;
        isEmpty(): boolean;
        length(unit?: string): number;
        overlaps(other: Interval): boolean;
        set(values: IntervalObject): Interval;
        splitAt(...dateTimes: DateTime[]): Interval[];
        splitBy(duration: Duration | DurationObject | number): Interval[];
        toDuration(unit: string | string[], options?: DiffOptions): Duration;
        toFormat(dateFormat: string, options?: {
            seperator?: string,
        }): string;
        toISO(options?: Object): string;
        toString(): string;
        union(other: Interval): Interval;
    }

    class Settings {
        static defaultLocale: string;
        static defaultNumberingSystem: string;
        static defaultOutputCalendar: string;
        static defaultZone: Zone;
        static defaultZoneName: string;
        static now: Function;
        static throwOnInvalid: Zone;
        static resetCache(): void;
    }

    type ZoneOffsetOptions = {
        format?: 'short' | 'long',
        localeCode?: string,
    }

    class Zone {
        static offsetName(ts: number, options?: ZoneOffsetOptions): string;
        static isValid: boolean;
        static name: string;
        static type: string;
        static universal: boolean;
        equals(other: Zone): boolean;
        static offset(ts: number): number;
    }
}

@marudor
Copy link

marudor commented Dec 4, 2017

Oh. You found my types.
I planned on submitting them to https://github.com/flowtype/flow-typed as I am also a maintainer there.
Haven't hat time to write tests for it though.

The types I did were made on a 4 hour train ride and I pretty much used the Documentation to make them. So it might also be a good hint where the documentation lacks information.

If you need any help with flow types I'm happy to help.
If you want to flowify the codebase and generate types based on that I would be happy to help you with that as well.

@tom10271
Copy link

tom10271 commented Dec 4, 2017

I have tried to build something with the converted d.ts file. It is working well.

Thank you so much for your work @marudor. It helped a lot for TypeScript users. I can't believe another library can help other and glad it does

@OliverJAsh
Copy link

I'm starting to use the typings provided above by @marudor and @tom10271 (in TypeScript) and making various corrections as I go along. How can we collaborate? Perhaps we could add them to DefinitelyTyped.

@chriskrycho
Copy link

Alternatively you could do what we have done for Ember.JS, and create a small repository for rapid it’s ration until they are stable, and then upstream them.

@OliverJAsh
Copy link

I've made various improvements today whilst integrating Luxon into my project. Below is the diff from the typings pasted above by @tom10271, and here is the complete set: https://gist.github.com/OliverJAsh/7ee1673dd305da0c34958e5d719417aa

diff --git a/src/server/typings/luxon-before.d.ts b/src/server/typings/luxon.d.ts
index 12451ad..f3f1ef4 100644
--- a/src/server/typings/luxon-before.d.ts
+++ b/src/server/typings/luxon.d.ts
@@ -1,8 +1,5 @@
 declare module 'luxon' {
-    export = luxon;
-}
-
-declare namespace luxon {
+    namespace luxon {
         type DateTimeFormat = any;
         type ZoneOptions = {
             keepCalendarTime?: boolean;
@@ -29,8 +26,8 @@ declare namespace luxon {
             zone?: string | Zone;
         };
 
-    type DateObject = {
-        yearh?: number;
+        type DateObjectUnits = {
+            year?: number;
             day?: number;
             ordinal?: number;
             weekYear?: number;
@@ -40,6 +37,9 @@ declare namespace luxon {
             minute?: number;
             second?: number;
             millisecond?: number;
+        };
+
+        type DateObject = DateObjectUnits & {
             zone?: string | Zone;
             locale?: string;
             outputCalendar?: string;
@@ -78,7 +78,11 @@ declare namespace luxon {
             static fromObject(obj: DateObject): DateTime;
             static fromRFC2822(text: string, options?: DateTimeOptions): DateTime;
             static fromString(text: string, format: string, options?: DateTimeOptions): DateTime;
-        static fromStringExplain(text: string, format: string, options?: DateTimeOptions): Object;
+            static fromStringExplain(
+                text: string,
+                format: string,
+                options?: DateTimeOptions,
+            ): Object;
             static invalid(reason: any): DateTime;
             static local(
                 year?: number,
@@ -89,7 +93,7 @@ declare namespace luxon {
                 second?: number,
                 millisecond?: number,
             ): DateTime;
-        static max(...dateTimes: DateTime[]): DateTime;
+            static max(...dateTimes: DateTime[]): DateTime | undefined;
             static min(...dateTimes: DateTime[]): DateTime;
             static utc(
                 year?: number,
@@ -133,11 +137,13 @@ declare namespace luxon {
             equals(other: DateTime): boolean;
             get(unit: string): number;
             hasSame(other: DateTime, unit: string): boolean;
-        minus(duration: Duration | number | Object): DateTime;
+            minus(duration: Duration): DateTime;
+            minus(milliseconds: number): DateTime;
+            minus(durationObject: Partial<DurationObject>): DateTime;
             plus(duration: Duration | number | Object): DateTime;
             reconfigure(properties: Object): DateTime;
             resolvedLocaleOptions(options?: Object): Object;
-        set(values: DateObject): DateTime;
+            set(values: DateObjectUnits): DateTime;
             setLocale(locale: any): DateTime;
             setZone(zone: string | Zone, options?: ZoneOptions): DateTime;
             startOf(unit: string): DateTime;
@@ -301,7 +307,8 @@ declare namespace luxon {
             static defaultZone: Zone;
             static defaultZoneName: string;
             static now: Function;
-        static throwOnInvalid: Zone;
+            static throwOnInvalid: boolean;
             static resetCache(): void;
         }
 
@@ -320,3 +327,6 @@ declare namespace luxon {
             static offset(ts: number): number;
         }
     }
+
+    export = luxon;
+}

@ghost
Copy link

ghost commented Dec 14, 2017

So I made a PR on DefinitelyTyped for luxon based on @OliverJAsh and @marudor's types. I had to tweak a few things to get them to work with DT's tslint configs. I also added the toLocaleString function. If anyone wants to look this over and let me know if i did something wrong here, also glad to add anyone else to the contributors at the top of the types file so you will get notified on updates. DefinitelyTyped/DefinitelyTyped#22203

@icambron
Copy link
Member

Summary of current efforts:

@ghost
Copy link

ghost commented Dec 23, 2017

The type definition got merged in to DefinitelyTyped. You should now be able to use npm i @types/luxon 🎊 Happy Holidays! 🎆

@icambron
Copy link
Member

I'll add some stuff to the docs

@icambron
Copy link
Member

Added docs for both flow-typed and DefinitelyTyped in fc4a10f. You can see them here. Thanks everyone!

@mhagmajer
Copy link

Could you please update the Flow definitions for the latest API changes (0.4.0)?

@icambron
Copy link
Member

icambron commented Feb 2, 2018

This isn't the right place for that -- you want to report that in the FlowType repository

@mhagmajer
Copy link

@icambron would you consider adding these type definitions to the library itself? It might help to keep these consistent in the future.

@icambron
Copy link
Member

icambron commented Feb 2, 2018

@mhagmajer no, I really don't want to do that. I don't use Flow or Typescript and I'm uninterested in maintaining the definitions.

@mhagmajer
Copy link

Fair enough. Let me ping those guys then. Thanks!

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

No branches or pull requests

10 participants