Unknown syntax in typescript interface - syntax

I have a definition file with this in it:
interface _Form {
Dump:string;
}
interface Form extends _Form { constructor:{ new():Form }; }
What is the meaning of constructor:{ new():Form };?
If I try to implement this interface with this:
class MyForm implements Form {
Dump:string;
}
I get this error:
Class 'MyForm' incorrect implements interface 'Form'.
Types of property 'constructor' are incompatible.
Type 'Function' is not assignable to type 'new() => Form'.
Type 'Function' provides no match for signature 'new(): Form'

What you did is defined that Form has a property named constructor and it's a Form constructor (that is, a function which returns a new instance of Form).
To explain, consider the following:
class Form {}
type FormConstructor = { new(): Form };
let formCtor: FormConstructor = Form;
let form: Form = new formCtor();
You can also define static properties/functions this way:
class Form {
private dump: string;
constructor() {}
static fromDump(dump: string): Form {
let form = new Form();
form.dump = dump;
return form;
}
}
type FormConstructor = {
new(): Form;
fromDump: (dump: string) => Form;
};
let form1: Form = new Form();
let form2: Form = Form.fromDump("dump");
let formCtor: FormConstructor = Form;
let form3: Form = new formCtor();
let form4: Form = formCtor.fromDump("dump");
A good example for this is the Array (lib.ts & lib.es6.ts) and ArrayConstructor (lib.d.ts & lib.es6.d.ts).
In your case though I don't see a reason for this, and you probably just want to define a class constructor:
interface Form {
dump: string;
}
class MyForm implements Form {
dump: string;
constructor(dump: string) {
this.dump = dump;
}
}
You don't need to specify in the interface that implementing classes need to have a ctor, that's a given.
Edit
If that interface is auto generated then you need to stop using whatever it is that generates it because it's doing an awful job.
That interface is (I'm pretty sure) impossible to implement, here's something close:
interface _Form {
Dump:string;
}
interface Form extends _Form { ctor:{ new():Form }; }
class MyForm implements Form {
public ctor: { new():Form };
public Dump: string;
constructor() {
this.ctor = MyForm;
}
}
(code in playground)
It's exactly the same except that I changed it from constructor to ctor, and it compiles fine (though still it makes no sense).
If you change the ctor to constructor:
class MyForm implements Form {
public constructor: { new():Form };
public Dump: string;
constructor() {
this.constructor = MyForm;
}
}
you'll get errors because the class constructor (which is a keyword) needs to be a function and only one using that name.

Related

how to convert to NotNull by using enum in Kotlin

How can I convert the following code to accepted NotNull inside enum class by using Kotlin?
Note: i'm using this enum between two activity and one activity has 2 adapters.
Here is enum class
enum class Adapterx {
ADAPTER_1,
ADAPTER_2;
companion object {
fun fromOrdinal(ordinal: Int): Adapterx? {
return Adapterx.values().firstOrNull { it.ordinal == ordinal }
}
}
}
Since you cannot restrict the ordinal: Int parameter as you've define it, you have two choices if you receive an ordinal which is not part of the enum, or is out of bounds:
Return a default value
Throw an exception
IMHO both cases are plausible if you document properly the method.
Here's a case where you return just a default value if you ask for an ordinal that does not exist:
class KotlinEnumTest {
enum class Adapterx {
ADAPTER_1,
ADAPTER_2;
companion object {
val defaultValue = ADAPTER_1
fun fromOrdinal(ordinal: Int): Adapterx =
Adapterx.values().getOrElse(ordinal, { _ -> defaultValue })
}
}
#Test fun testEnumOrdinals() {
val resultAdapter1 = Adapterx.fromOrdinal(0)
Assert.assertEquals(Adapterx.ADAPTER_1, resultAdapter1)
val resultAdapter2 = Adapterx.fromOrdinal(1)
Assert.assertEquals(Adapterx.ADAPTER_2, resultAdapter2)
// The following returns the default value ADAPTER_1
val resultOrdinalIndexOutOfBounds = Adapterx.fromOrdinal(2)
Assert.assertEquals(Adapterx.ADAPTER_1, resultOrdinalIndexOutOfBounds)
}
}

Type variable in protocol - Swift 2

So I have a protocol, and in it I want a variable that is a class type. That way I can init that class from the variable.
Keep in mind that there will be many different classes. I made a quick example.
I get the error "type 'CashRegister' does not conform to protocol 'RegisterProtocol'"
This example isn't exactly what I'm doing, but it gets the point across. Thanks for the help.
protocol RegisterProtocol {
var currentBill: DollarBillProtocol {get set}
func makeNewBill()->DollarBillProtocol
}
extension RegisterProtocol {
func printCurrentBill() {
Swift.print(currentBill)
}
}
class CashRegister: RegisterProtocol {
var currentBill = OneDollarBill.self
func makeNewBill() -> DollarBillProtocol {
return currentBill.init()
}
}
protocol DollarBillProtocol {
// protocol that all bills have in common
}
class OneDollarBill: DollarBillProtocol {
required init(){
}
}
class FiveDollarBill: DollarBillProtocol {
required init(){
}
}
The way you declare currentBill in CashRegister makes it a var of type class. But the protocol RegisterProtocol requires this variable to be of type DollarBillProtocol in any class that implements the protocol. The compile error is because of this mismatch.
To make this more clear, you could declare the var with the explicit type, as follows:
class CashRegister: RegisterProtocol {
var currentBill: DollarBillProtocol = OneDollarBill() // or other initial value
}

TypeScript constructor - ambient contexts error

How do I create a constructor in TypeScript?
Looked at a bunch of guides, but the syntax must've changed. Here's my latest attempt:
car.d.ts
declare class Car {
constructor(public engine: string) {
this.engine = engine + "foo";
}
}
Error:
An implementation cannot be called in ambient contexts.
By using declare you're defining a class type. The type is only defined, and shouldn't have an implementation, so declare needs to be removed. Then it compiles fine.
class Car {
constructor(public engine: string) {
this.engine = engine + "foo";
}
}
However that code compiles to:
var Car = (function () {
function Car(engine) {
this.engine = engine;
this.engine = engine + "foo";
}
return Car;
})();
which sets the engine property twice.
That probably wasn't what you intended, so the engine property should be defined on the class, not the constructor.
class Car {
public engine: string;
constructor(engine: string) {
this.engine = engine + "foo";
}
}
Edit:
The error you received about needing declare was due to you using the .d.ts extension for definition files. The extension should be just .ts if you want the file to compile to JavaScript.
Edit 2:
declare class Car {
public engine;
constructor(engine: string);
}

Add functions to an Enum

Is it possible to add functions to an Enum type in TypeScript?
for example:
enum Mode {
landscape,
portrait,
// the dream...
toString() { console.log(this); }
}
Or:
class ModeExtension {
public toString = () => console.log(this);
}
enum Mode extends ModeExtension {
landscape,
portrait,
}
Of course the toString() function would contain something like a switch But a use-case would flow along the lines of:
class Device {
constructor(public mode:Mode) {
console.log(this.mode.toString());
}
}
I understand why extending an enum might be a strange thing, just wondering if it is possible.
You can either have a class that is separate to the Enum and use it to get things you want, or you can merge a namespace into the Enum and get it all in what looks like the same place.
Mode Utility Class
So this isn't exactly what you are after, but this allows you to encapsulate the "Mode to string" behaviour using a static method.
class ModeUtil {
public static toString(mode: Mode) {
return Mode[mode];
}
}
You can use it like this:
const mode = Mode.portrait;
const x = ModeUtil.toString(mode);
console.log(x);
Mode Enum/Namespace Merge
You can merge a namespace with the Enum in order to create what looks like an Enum with additional methods:
enum Mode {
X,
Y
}
namespace Mode {
export function toString(mode: Mode): string {
return Mode[mode];
}
export function parse(mode: string): Mode {
return Mode[mode];
}
}
const mode = Mode.X;
const str = Mode.toString(mode);
alert(str);
const m = Mode.parse(str);
alert(m);
You can get the string value of an non-const enum by using square brackets:
class Device {
constructor(public mode:Mode) {
console.log(Mode[this.mode]);
}
}
You can also put some enum-specific util functions into the enum, but that's just like static class members:
enum Mode {
landscape,
portrait
}
namespace Mode {
export function doSomething(mode:Mode) {
// your code here
}
}
Convert your enum to the enum pattern. I find this is a better practice in general for many languages, since otherwise you restrict encapsulation options for your type. The tendency is to switch on the enum value, when really any data or functionality that is dependent on the particular enum value should just go into each instance of the enum. I've added some more code to demonstrate.
This might not work if you are particularly dependent on the underlying enum values. In that case you would need to add a member for the old values and convert places that need it to use the new property.
class Mode {
public static landscape = new Mode(1920, 1080);
public static portrait = new Mode(1080, 1920);
public get Width(): number { return this.mWidth; }
public get Height(): number { return this.mHeight; }
// private constructor if possible in a future version of TS
constructor(
private mWidth: number,
private mHeight: number
) {
}
public GetAspectRatio() {
return this.mWidth / this.mHeight;
}
}
An addition to Fenton's solution.
If you want to use this enumerator in another class, you need to export both the enum and the namespace. It would look like this:
export enum Mode {
landscape,
portrait
}
export namespace Mode {
export function toString(mode: Mode): string {
return Mode[mode];
}
}
Then you just import the mode.enum.ts file in your class and use it.
can make enum like by private constructor and static get return object
export class HomeSlideEnum{
public static get friendList(): HomeSlideEnum {
return new HomeSlideEnum(0, "friendList");
}
public static getByOrdinal(ordinal){
switch(ordinal){
case 0:
return HomeSlideEnum.friendList;
}
}
public ordinal:number;
public key:string;
private constructor(ordinal, key){
this.ordinal = ordinal;
this.key = key;
}
public getTitle(){
switch(this.ordinal){
case 0:
return "Friend List"
default :
return "DChat"
}
}
}
then later can use like this
HomeSlideEnum.friendList.getTitle();
ExtendedEnum Class
I always loved the associated types in Swift and I was looking to extend Typescript's enum basic functionality. The idea behind this approach was to keep Typescript enums while we add more properties to an enum entry. The proposed class intends to associate an object with an enum entry while the basic enum structure stays the same.
If you are looking for a way to keep vanilla Typescript enums while you can add more properties to each entry, this approach might be helpful.
Input
enum testClass {
foo = "bar",
anotherFooBar = "barbarbar"
}
Output
{
entries: [
{
title: 'Title for Foo',
description: 'A simple description for entry foo...',
key: 'foo',
value: 'bar'
},
{
title: 'anotherFooBar',
description: 'Title here falls back to the key which is: anotherFooBar.',
key: 'anotherFooBar',
value: 'barbarbar'
}
]
}
Implementation
export class ExtendedEnum {
entries: ExtendedEnumEntry[] = []
/**
* Creates an instance of ExtendedEnum based on the given enum class and associated descriptors.
*
* #static
* #template T
* #param {T} enumCls
* #param {{ [key in keyof T]?: EnumEntryDescriptor }} descriptor
* #return {*} {ExtendedEnum}
* #memberof ExtendedEnum
*/
static from<T extends Object>(enumCls: T, descriptor: { [key in keyof T]?: EnumEntryDescriptor }): ExtendedEnum {
const result = new ExtendedEnum()
for (const anEnumKey of Object.keys(enumCls)) {
if (isNaN(+anEnumKey)) { // skip numerical keys generated by js.
const enumValue = enumCls[anEnumKey]
let enumKeyDesc = descriptor[anEnumKey] as EnumEntryDescriptor
if (!enumKeyDesc) {
enumKeyDesc = {
title: enumValue
}
}
result.entries.push(ExtendedEnumEntry.fromEnumEntryDescriptor(enumKeyDesc, anEnumKey, enumValue))
}
}
return result
}
}
export interface EnumEntryDescriptor {
title?: string
description?: string
}
export class ExtendedEnumEntry {
title?: string
description?: string
key: string
value: string | number
constructor(title: string = null, key: string, value: string | number, description?: string) {
this.title = title ?? key // if title is not provided fallback to key.
this.description = description
this.key = key
this.value = value
}
static fromEnumEntryDescriptor(e: EnumEntryDescriptor, key: string, value: string | number) {
return new ExtendedEnumEntry(e.title, key, value, e.description)
}
}
Usage
enum testClass {
foo = "bar",
anotherFooBar = "barbarbar"
}
const extendedTestClass = ExtendedEnum.from(testClass, {
foo: {
title: "Title for Foo",
description: "A simple description for entry foo..."
},
anotherFooBar: {
description: "Title here falls back to the key which is: anotherFooBar."
}
})
Advantages
No refactor needed, keep the basic enum structures as is.
You get code suggestions for each enum entry (vs code).
You get an error if you have a typo in declaring the enum descriptors aka associated types.
Get the benefit of associated types and stay on top of OOP paradigms.
It is optional to extend an enum entry, if you don't, this class generates the default entry for it.
Disadvantages
This class does not support enums with numerical keys (which shouldn't be annoying, because we usually use enums for human readability and we barely use numbers for enum keys)
When you assign a numerical value to a key; Typescript double-binds the enum key-values. To prevent duplicate entries, this class only considers string keys.

Class variables not yet supported

I begin my project with a split view controller as initial view controller and start it automatically from storyboard.
Generally, an app with this UI have one and only one split view controller as root, so I create a static variable in the subclass and set it when initialisation was done.
So I want try this behaviour with swift.
I read the Swift programming language guide book on iBook about Type properties (with static and class keyword) and trying a piece of code to the job:
import UIKit
class SplitViewController: UISplitViewController {
class func sharedInstance() -> SplitViewController {
return SplitViewController.instance
}
class let instance: SplitViewController = nil
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.initialization()
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder);
self.initialization()
}
func initialization() {
SplitViewController.instance = self;
}
}
but I figured out when Xcode say the class keyword for type properties wasn't supported yet.
Did you have a solution to do this ?
Embedding a struct can work just fine as a workaround:
class SomeClass
{
// class var classVariable: Int = 0
// "Class variables not yet supported." Weird.
// Workaround:
private struct SubStruct { static var staticVariable: Int = 0 }
class var workaroundClassVariable: Int
{
get { return SubStruct.staticVariable }
set { SubStruct.staticVariable = newValue }
}
}
The SomeClass.workaroundClassVariable computed type property can then be used as if it were a stored type property.
Swift now has support for static variables in classes. This is not exactly the same as a class variable (because they aren't inherited by subclasses), but it gets you pretty close:
class X {
static let y: Int = 4
static var x: Int = 4
}
println(X.x)
println(X.y)
X.x = 5
println(X.x)
It seems to be possible to declare variables with static storage duration in file scope (as in C):
var sharedInstance: SplitViewController? = nil
class SplitViewController: UISplitViewController {
....
func initialization() {
sharedInstance = self
}
}
My preferred method is to just use a private file scope var outside of the class and then implement class/static getters and setters:
private var _classVar: Int = 0;
class SomeClass
{
public class var classVar: Int
{
get { return _classVar }
set { _classVar = newValue }
}
}
As of Swift 1.2 (available with Xcode 6.3b1 and onwards), static class properties and methods are supported.
class SomeClass
{
static var someVariable: Int = 0
}
Using a dispatch_once singleton model in Swift
Seems to be the best answer so far, avoiding the use of a global variable.
A solution enough similar than var in file scope but more customisable and near singleton is to use a struct which support static var as property of class
struct PersonSharedData {
static var backstore = ""
var data: String {
get { return PersonSharedData.backstore }
set { PersonSharedData.backstore = newValue }
}
}
class Person {
var shared=PersonSharedData() //<< pseudo class var
var family: String {
get { return shared.data }
set { shared.data=newValue }
}
var firstname = ""
var lastname = ""
var sexe: Sexe = .Unknown
}
Ok, with the solution of Nikolai that do the work. I post my changes in this thread for information
var instance: SplitViewController? = nil
class SplitViewController: UISplitViewController {
class func sharedInstance() -> SplitViewController? {
return instance;
}
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.initialization()
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder);
self.initialization()
}
func initialization() {
instance = self
}
}
and for example, in my appDelegate, I can access this static method like this
SplitViewController.sharedInstance()!.presentsWithGesture = false
The wording in the error heavily implies this will be a language feature in the future.
You may want to resort temporarily to declaring a property variable in the Application Delegate and retrieve it from there. Not ideal, definitely an anti-pattern, but would give you a central place to retrieve the UISplitViewController when needed.
You have to wrap the class variables inside an inner struct variable
class Store{
var name:String
var address:String
var lat:Int
var long:Int
init(name:String, address:String, lat:Int, long:Int){
self.name = name
self.address = address
self.lat = lat
self.long=long
}
private struct FACTORY_INITIALIZED_FLAG { static var initialized: Bool = false
static var myStoreList:[Store]?
static func getMyStoreList()->[Store]{
if !initialized{
println("INITIALIZING")
myStoreList = [
Store(name: "Walmart", address: "abcd", lat: 10, long: 20),
Store(name: "JCPenny", address: "kjfnv", lat: 23, long: 34)
]
initialized = true
}
return myStoreList!
}
}
}
var a = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()
var b = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()
// only prints INITIALIZING once
Try this:
class var instance: SplitViewController {
return nil
}
It is called Type Property in Swift.
You define type properties with the static keyword. For computed type properties for class types, you can use the class keyword instead to allow subclasses to override the superclass’s implementation. The example below shows the syntax for stored and computed type properties:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
Read more at link below,
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID254

Resources